﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#include "GnufPropertyPallet.h"
#include "GbmpNew.h"
#include "GnufPallet.h"
#include "GnufUtility.h"
#include "GnufArrangementArea.h"
#include "QtGnufPropertyPallet.h"
#include "IParameter.h"
#include "ElementId.h"
#include "ISelection.h"
#include "ContainerUtil.h"
#include "IDocument.h"
#include "IUiDocument.h"
#include "IUiDocumentViewManager.h"
#include "IGraphicsNodeReference.h"
#include "IUiView.h"
#include "IModelView.h"
#include "IElementBasicInformation.h"
#include "ElementsChangeEventType.h"
#include "IEndOfTransactionProcessor.h"
#include "UiCommonDialog.h"
#include "GnufFamilyTypes.h"
#include "GnufIParameterDisplayCustom.h"
#include "GnufTree.h"
#include "GnufPropertyPalletUiViewEventHandler.h"
#include "IUiDocumentEvent.h"
#include "IUiViewEvent.h"
#include "GbmpQuickCast.h"
#include "IUserTransaction.h"
#include "IInstanceType.h"
#include "IFamilyType.h"
#include "IFamily.h"
#include "GnufInfo.h"
#include "TranslatorManager.h"
#include "GnufNameValuePairs.h"
#include "IParameterDefinition.h"
#include "IParameterGroupsFilter.h"
#include "IParameterGroupSorter.h"
#include "IElementParameterGroupSorterManager.h"
#include "IElementParameters.h"
#include "IParameterDefinitionLibrary.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "ILinkElementProxy.h"
#include "IParameterDisplayManager.h"
#include "GnufParameterDisplayCustomFactory.h"
#include "IParameterDisplayDropdownList.h"
#include "GnufList.h"
#include "GnufText.h"
#include "GnufCheck.h"
#include "GnufUiCommonDef.h"
#include "IParameterDisplayEditbox.h"
#include "IParameterDisplayEditboxWithButton.h"
#include "IParameterDisplayCheckbox.h"
#include "ParameterType.h"
#include "IParameterValueStorage.h"
#include "ISelectionChangeEvent.h"
#include "GnufPropertyPalletSelectionChangeEventHandler.h"
#include "IElementsChangeEventHandler.h"
#include "IElementsChangeEventArgs.h"
#include "GnufPropertyPanelEvent.h"
#include "IGenericElement.h"
#include "IGenericType.h"
#include "IInstance.h"
#include "PropertyPanelEventTypeDefines.h"
#include "IParameterValueList.h"
#include "IParameterValidator.h"
#include "IParameterValueString.h"
#include "GraphicsMaterialLibraryDialogEventsScope.h"
#include "IPresetParameterManager.h"
#include "IRegenerator.h"
#include "JournalUtils.h"
#include "FamilySolverUtils.h"
#include "IFamilyGeometryConstraint.h"


#include "ICopyOperator.h"
#include "GnufParameterPreviewUtils.h"
#include "IMaterialSelectionDialogListener.h"
#include "IParameterValueElementId.h"
#include "IGraphicsMaterial.h"
#include "GnufPropertyPalletUiDocEventHandler.h"
#include "GnufBlock.h"
#include "GnufButtonEx.h"
#include "IFamilyManager.h"
#include "GnufBindToFamilyParamDlg.h"
#include "GnufAppearanceSetting.h"
#include "UserTransactionUtils.h"
#include "GbmpFileSystem.h"
#include "GnufColorControl.h"
#include "ICategory.h"
#include "ICategoryLibrary.h"
#include "GnufPushButton.h"
#include "GnufLineStyleParameterDisplay.h"
#include "IElementParameterBindings.h"
#include "IParameterDefinitionLibrary.h"
#include "IFamilyGeneralForm.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "IFamilyMultiDistanceDimension.h"
#include "IFamilyExternalForm.h"
#include "GnufArrangementAreaEvents.h"
#include "GnufPreferences.h"
#include "GnufWorkBench.h"
#include "FamilyHighlightUtils.h"
#include "IFamilyRapidForm.h"
#include "IParameterValueDisplayString.h"
#include "IEditMode.h"
#include "IFamilySketch2D.h"
#include "IFamilyExtrusion.h"
#include "IFamilySweep.h"
#include "IFamilySweptLoft.h"
#include "FamilyElementUtils.h"
#include "IFamilyRapidShape.h"
#include "NestedInstanceUtils.h"
#include "IGraphicsMaterial.h"
#include "ParameterUtils.h"
#include "ITextStyleManager.h"

#include "IElement.h"
#include "GnufModelViewDefine.h"
#include "GnufQtWorkBenchWindow.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gnuf;
using namespace gcmp;
using namespace gfam;


namespace {
    static const std::wstring s_key(L"新属性面板");
    static const std::wstring iconPath = L":/images/FamilyType/Default";
    static const std::wstring multiValueText = L"*多种*";
    static const std::wstring multiTypeText = L"*多种类型*";
    static const std::wstring multiCategoryText = L"*多种构件*";
    static const std::wstring emptyValueText = L"";

    static gcmp::OwnerPtr<gfam::FamilyTypeIntegratedComponent> s_familyTypeComponentBuilder = nullptr;
    static gcmp::OwnerPtr<gfam::InstanceNameValuePairsComponent> s_instanceNameValuePairsBuilder = nullptr;

    // 针对选中的Element更新的监听，用于监听属性表显示的Element改变（不会被其它类使用）
    class SelElementChangeObserver : public IElementsChangeEventHandler
    {
    public:
        SelElementChangeObserver(gfam::GnufPropertyPallet* pPropertyPallet)
            :m_pPropertyPallet(pPropertyPallet)
        {
            DBG_WARN_UNLESS(pPropertyPallet != nullptr, L"pPropertyPallet不能为空", L"paramodel", L"2024-02-20");
        }
    private:
        SelElementChangeObserver()
        {
        }

        void On(IElementsChangeEventArgs* pArgs) override
        {
            if (!pArgs)
                return;

            const std::vector<const IElement*>& elements = pArgs->GetElements();
            if (elements.empty())
                return;

            if (!m_pPropertyPallet
                || !m_pPropertyPallet->IsVisible()
                || !m_pPropertyPallet->GetInstanceNameValuePairsBuilder()
                || m_pPropertyPallet->GetInstanceNameValuePairsBuilder()->IsNeedUpdate())
                return;

            const std::vector<ElementId> selElements = m_pPropertyPallet->HasSelectedElements() ? m_pPropertyPallet->GetSelectedElements() : m_pPropertyPallet->GetSourceElements();
            if (selElements.empty())
                return;

            FOR_EACH(element, elements)
            {
                if (!element)
                    continue;

                if (!element->GetBasicInformation())
                    continue;

                const ElementId& id = element->GetBasicInformation()->GetElementId();

                if (std::find(selElements.begin(), selElements.end(), id) != selElements.end())
                {
                    m_pPropertyPallet->GetInstanceNameValuePairsBuilder()->SetNeedUpdate(true);
                }
            }
        }

    private:
        gfam::GnufPropertyPallet* m_pPropertyPallet;
    };

    // 文档事务提交监听，用于触发更新属性表时机
    class EndOfTransactionProcessorPropertyPallet : public gcmp::IEndOfTransactionProcessor
    {
    public:
        EndOfTransactionProcessorPropertyPallet(gfam::GnufPropertyPallet* pPropertyPallet)
            :m_pPropertyPallet(pPropertyPallet), m_id(IEndOfTransactionProcessor::GenerateId())
        {
            DBG_WARN_UNLESS(pPropertyPallet != nullptr, L"pPropertyPalette不能为空", L"paramodel", L"2024-02-20");
        }
    public:
        virtual void Process(IDocument* pDoc) override
        {
            if (m_pPropertyPallet
                && m_pPropertyPallet->GetInstanceNameValuePairsBuilder()
                && m_pPropertyPallet->GetInstanceNameValuePairsBuilder()->IsNeedUpdate()
                && m_pPropertyPallet->GetInstanceNameValuePairsBuilder()->IsConnected()) // 事务提交且属性表需要更新，则立即更新
            {
                m_pPropertyPallet->Refresh();
            }
        }

        virtual Int64 GetId() const override { return m_id; }

    private:
        Int64 m_id;
        gfam::GnufPropertyPallet* m_pPropertyPallet;
    };


    class GnufElementPropertyPalletMaterialSelectionDialogEvents : public gcmp::IMaterialSelectionDialogListener
    {
    public:
        GnufElementPropertyPalletMaterialSelectionDialogEvents(const IDocument* pDocument, int parameterDefinitionId)
            :m_pDocument(pDocument), m_parameterDefinitionId(parameterDefinitionId)
        {

        }

        virtual void OnApplyMaterial(const ElementId& materialId, bool isConfirmButtonClicked) override
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDocument, L"m_pDocument不存在", L"paramodel", L"2024-02-20");

            if (!materialId.IsValid())
            {
                return;
            }

            gfam::GnufPropertyPallet* pPropPalette = gfam::GnufPropertyPallet::Get();
            if (!pPropPalette)
            {
                DBG_WARN(L"pPropPalette不存在", L"paramodel", L"2024-02-20");
                return;
            }

            gfam::InstanceNameValuePairsComponent* pPropertyPalletChildComponent = pPropPalette->GetInstanceNameValuePairsBuilder();
            if (!pPropertyPalletChildComponent)
            {
                DBG_WARN(L"pPropertyPalletChildComponent不存在", L"paramodel", L"2024-02-20");
                return;
            }

            pPropertyPalletChildComponent->SetPropertyTableCanBeUpdated(isConfirmButtonClicked);

            IGraphicsMaterial* pMaterialElement = quick_cast<IGraphicsMaterial>(m_pDocument->GetElement(materialId));

            if (pMaterialElement == nullptr)
            {
                UiCommonDialog::ShowMessageBox(GBMP_TR(L"发生错误"), GBMP_TR(L"材质创建失败！"), (int)UiCommonDialog::ButtonType::OK);
                return;
            }
            OwnerPtr<IParameterValueStorage> opParameterValueStorage = IParameterValueElementId::Create(pMaterialElement->GetElementId());
            pPropertyPalletChildComponent->RefreshByParameterValueStorage(opParameterValueStorage.get(), m_parameterDefinitionId);
        }

        virtual void OnCloseDialog(bool isConfirmButtonClicked) override
        {
            gfam::GnufPropertyPallet *pPropPalette = gfam::GnufPropertyPallet::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pPropPalette, L"PropertyPalette不存在", L"paramodel", L"2024-02-20");
            gfam::InstanceNameValuePairsComponent* pPropertyPalletChildComponent = pPropPalette->GetInstanceNameValuePairsBuilder();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pPropertyPalletChildComponent, L"pPropertyPalletChildComponent为空!", L"paramodel", L"2024-02-20");
            pPropertyPalletChildComponent->SetPropertyTableCanBeUpdated(true);
        }

    private:
        const IDocument* m_pDocument;
        int m_parameterDefinitionId;
    };

    static void GroupAndSortParameters(
        const gcmp::IElement* pElement,
        const std::vector<ElementId>& selElements,
        const std::vector<gcmp::OwnerPtr<gcmp::IParameter>>& commonParams,
        const std::vector<bool>& paramMultiVals,
        gcmp::GroupNameParametersArray& outGroupParameters,
        std::map<int, bool>& outParamDefIdToIsParamMultiVals)
    {
        outGroupParameters.clear();

        std::map<UniIdentity, int> paramUidToParamIdx; // <ParamDefinitonUid, index_in_commonParams>
        std::map<int, bool> paramDefIdToIsParamMultiVals; //<ParamDefinitionId, is_param_multi_val>
                                                          // 把 commonParams 中参数分组
        std::vector<const IParameterDefinition*> allParameterDefs;
        for (int tmpParamIdx = 0; tmpParamIdx < (int)commonParams.size(); tmpParamIdx++)
        {
            const IParameterDefinition* paramDef = commonParams[tmpParamIdx]->GetParameterDefinition();
            const IParameterDefinition* pIParameterDefinition = dynamic_cast<const IParameterDefinition*>(paramDef);
            DBG_WARN_AND_CONTINUE_UNLESS(pIParameterDefinition != nullptr, L"pIParameterDefinition为空", L"paramodel", L"2024-02-20");
            allParameterDefs.push_back(pIParameterDefinition);

            // Uid->index
            if (paramUidToParamIdx.find(paramDef->GetUid()) == paramUidToParamIdx.end())
            {
                paramUidToParamIdx.insert(std::make_pair(paramDef->GetUid(), tmpParamIdx));
            }
            else
            {
                DBG_WARN(L"两个参数具有同样的DefinitionId", L"paramodel", L"2024-02-20");
            }

            // paramdefid->is_param_multi_val
            paramDefIdToIsParamMultiVals.insert(std::make_pair(paramDef->GetId(), paramMultiVals[tmpParamIdx]));
        }

        const IParameterGroupsFilter* pGroupsFilter = IParameterGroupsFilter::GetParameterGroupsFilter();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pGroupsFilter != nullptr, L"pGroupsFilter为空", L"paramodel", L"2024-02-20");

        std::unordered_set<std::wstring> unorderGroupNames;
        FOR_EACH(paramDef, allParameterDefs)
        {
            std::wstring groupName = pGroupsFilter->GetGroupName(paramDef);
            unorderGroupNames.emplace(groupName);
        }

        //GCMP平台层次的参数分组以及参数排序
        std::vector<std::wstring> allGroupNames(unorderGroupNames.begin(), unorderGroupNames.end());
        std::vector<size_t> groupsOrder = pGroupsFilter->SortGroups(allGroupNames);             //组别排序

        gcmp::GroupParameterUidsArray allGroupParameterUids;
        allGroupParameterUids.resize((int)groupsOrder.size());
        {
            for (int groupOrderIdx = 0; groupOrderIdx < (int)groupsOrder.size(); groupOrderIdx++)
            {
                std::vector<UniIdentity> emptyParams;
                const std::wstring& gname = allGroupNames[groupOrderIdx];

                allGroupParameterUids[groupsOrder[groupOrderIdx]] = std::make_pair(gname, emptyParams);
            }

            for (int paramOrderIdx = 0; paramOrderIdx < (int)allParameterDefs.size(); paramOrderIdx++)
            {
                const IParameterDefinition* tmpParamDef = allParameterDefs[paramOrderIdx];
                const std::wstring& gname = pGroupsFilter->GetGroupName(tmpParamDef);//allParameterDefs[paramIdx].GetData().GetGroupName();
                FOR_EACH(item, allGroupParameterUids)
                {
                    if (item.first == gname)
                    {
                        item.second.push_back(tmpParamDef->GetUid());
                        break;
                    }
                }
            }
        }

        GroupParameterUidsArray defOutGroupParameters;
        if (IElementParameterGroupSorterManager::GetSorter() != nullptr)
        {
            IElementParameterGroupSorterManager::GetSorter()->GroupAndSortParameters(allGroupParameterUids, defOutGroupParameters);
        }
        else
        {
            defOutGroupParameters.swap(allGroupParameterUids);
        }

        GroupParameterUidsArray sortedGroupParameterUids;
        if (selElements.size() == 1)
        {
            // 单选再看element的实例参数是否需要调整分组以及次序
            const IElementParameters* pElementParams = pElement->GetElementParameters();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pElementParams, L"element parameters不应为空", L"paramodel", L"2024-02-20");
            const IElementParameterGroupOverride* pGroupOverride = pElementParams->GetElementParameterGroupOverride();

            if (pGroupOverride)
                pGroupOverride->AdjustParameterGroup(defOutGroupParameters, sortedGroupParameterUids);
            else
                sortedGroupParameterUids.swap(defOutGroupParameters);
        }
        else
        {
            // 多选暂不进行参数实例层次调整
            sortedGroupParameterUids.swap(defOutGroupParameters);
        }

        // 输出outGroupParameters & outParamDefIdToIsParamMultiVals
        FOR_EACH(pairItem, sortedGroupParameterUids)
        {
            std::vector<OwnerPtr<IParameter>> eachGroupParameters;
            FOR_EACH(parameterUid, pairItem.second)
            {
                eachGroupParameters.emplace_back(commonParams[paramUidToParamIdx[parameterUid]]->Clone());
            }
            
            outGroupParameters.emplace_back(std::make_pair(pairItem.first, TransferOwnership(eachGroupParameters)));
        }

        outParamDefIdToIsParamMultiVals.swap(paramDefIdToIsParamMultiVals);
    }

    bool IsValidFamilyForInstance(const gcmp::IInstance* pInstance, const gcmp::IFamily* pFamily)
    {
        if (!pInstance || !pFamily)
            return false;

        const IFamily* pInstanceFamily = pInstance->GetFamily();
        if (pInstanceFamily == nullptr)
            return false;

        if (pFamily->GetFamilyServiceUid().HasSameValue(pInstanceFamily->GetFamilyServiceUid()))
            return true;

        std::vector<const IFamilyType*> famTypes = pFamily->GetFamilyTypes();
        IDocument* pDoc = pInstance->GetDocument();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc != nullptr, L"pDoc为空", L"paramodel", L"2024-02-20");

        return true;
    }

    bool GetCurrentParamValue(IDocument* pDoc, const gcmp::IParameter* param, const gnuf::Item* pItem, const std::vector<gcmp::ElementId>& elementIds, OwnerPtr<IParameterValueStorage>& opCurrentParamValue, bool &bCommitNow)
    {
        const IParameterDefinition* pParameterDefinition = param->GetParameterDefinition();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pParameterDefinition, L"pParameterDefinition为空!", L"paramodel", L"2024-02-20");
        IParameterDisplayManager* pParamDisplayMgr = IParameterDisplayManager::Get(pDoc);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pParamDisplayMgr, L"pParamDisplayMgr为空!", L"paramodel", L"2024-02-20");
        const IParameterDisplay* parameterDisplay = pParamDisplayMgr->GetParameterDisplay(pParameterDefinition->GetUid());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(gfam::GnufParameterDisplayCustomFactory::Get(), L"gfam::GnufParameterDisplayCustomFactory::Get()为空!", L"paramodel", L"2024-02-20");

        if (const IParameterDisplayDropdownList* pDropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(parameterDisplay))
        {
            const gnuf::List* pList = pItem->cast<gnuf::List>();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pList, L"pList is nullptr", L"paramodel", L"2024-02-20");

            std::wstring strCurValue = pList->Text();
            opCurrentParamValue = pDropdownList->GetValueByDisplayString(pDoc, strCurValue, elementIds);
            if (!opCurrentParamValue)
            {
                return false;
            }
            if (pDropdownList->GetParameterValueList() && pDropdownList->GetParameterValueList()->HasOuterEditor())
            {
                bCommitNow = true;
            }
        }
        else if (dynamic_cast<const IParameterDisplayEditbox*>(parameterDisplay) || dynamic_cast<const IParameterDisplayEditboxWithButton*>(parameterDisplay))
        {
            const gnuf::Text* pText = pItem->cast<gnuf::Text>();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pText, L"pText is nullptr", L"paramodel", L"2024-02-20");

            std::wstring itemValue = pText->text();
            QString strValue = QString::fromStdWString(itemValue).trimmed();
            if (ParameterDisplayUtils::GetValueAsDisplayString(param) != strValue.toStdWString())
            {
                OwnerPtr<IParameter> curParam = param->Clone();
                ParameterDisplayUtils::SetValueFromDisplayString(curParam.get(), strValue.toStdWString());
                if (curParam && curParam->GetParameterValueStorage())
                {
                    opCurrentParamValue = curParam->GetParameterValueStorage()->Clone();
                }
            }
        }
        else if (const IParameterDisplayCheckbox* pCheckbox = dynamic_cast<const IParameterDisplayCheckbox*>(parameterDisplay))
        {
            const gnuf::Check* pCheck = pItem->cast<gnuf::Check>();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pCheck, L"pCheck is nullptr", L"paramodel", L"2024-02-20");

            gnuf::CheckStatus boolCurValue = pCheck->checkState();
            OwnerPtr<IParameter> curParam = param->Clone();
            curParam->SetValueAsBool(boolCurValue != gnuf::CheckStatus::UnChecked);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(curParam->GetParameterValueStorage(), L"curParam->GetParameterValueStorage() is nullptr", L"paramodel", L"2024-02-20");
            opCurrentParamValue = curParam->GetParameterValueStorage()->Clone();
        }
        else if (gfam::IGnufParameterDisplayCustom* pDisplayCustom = gfam::GnufParameterDisplayCustomFactory::Get()->Find(pParameterDefinition->GetUid()))
        {
            OwnerPtr<IParameterValueStorage> opValueStorage = pDisplayCustom->GetValue(pDoc, elementIds, pItem);
            if (!opValueStorage)
            {
                return false;
            }

            opCurrentParamValue = TransferOwnership(opValueStorage);
        }
        else
        {
            if (!parameterDisplay)
                return false;
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"未知类型的ParameterDisplay", L"paramodel", L"2024-02-20");
        }
        const IParameterValueStorage* pValueStorage = param->GetParameterValueStorage();
        if (pValueStorage && opCurrentParamValue)
        {
            const IParameterValidator* pValidator = pValueStorage->GetValidator();
            if (pValidator)
                opCurrentParamValue->SetValidator(pValidator->Clone());
        }
        return opCurrentParamValue != nullptr;
    }

    bool CheckConstraintIsAllowedToModify(IDocument* pDoc,IElement* pElement, gcmp::IParameter* param)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc不能为空！", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement, L"pElement不能为空！", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param不能为空！", L"paramodel", L"2024-02-20");

        const IParameterDefinitionLibrary* pParamDefLib = IParameterDefinitionLibrary::Get(pDoc);
        if (pParamDefLib)
        {
            if ((param->GetParameterDefinitionId() == pParamDefLib->GetParameterDefinitionIdByUid(PARAMETER_UID(RadialArrayRadiusBuiltInParameter))))
            {
                IGenericElement *pGenericElement = quick_cast<IGenericElement>(pElement);
                if (pGenericElement)
                {
                }
            }
        }

        return true;
    }

    bool SaveParamValueToElement(IDocument* pDoc, IElement* pElement, gcmp::IParameter* param, OwnerPtr<IParameterValueStorage>& opCurrentParamValue, bool& bParameterChanged)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement, L"pElement为空", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param为空", L"paramodel", L"2024-02-20");

        if (!CheckConstraintIsAllowedToModify(pDoc, pElement, param))
            return false;

        bParameterChanged = false;
        if (opCurrentParamValue != nullptr)
        {
            OwnerPtr<IParameterValueStorage> tempStringValue = IParameterValueString::Create(L"更多材质");
            if (quick_cast<IParameterValueString>(opCurrentParamValue.get()) && opCurrentParamValue->HasSameValue(tempStringValue.get()))
            {
                std::wstring strToken(L"");
                std::wstring strLibIdList(L"");
                std::wstring strProductCode(L"");

                ElementId materialId = ElementId::InvalidID;
                UiCommonDialog::ShowMaterialSelectionDialog(pDoc, materialId, strToken, strLibIdList, strProductCode);

                return false;
            }
            else
            {
                const IParameterValueStorage* parameterValue = param->GetParameterValueStorage();
                if (parameterValue != nullptr && !parameterValue->HasSameValue(opCurrentParamValue.get()))
                {
                    gcmp::OwnerPtr<gcmp::IUserTransaction> ut = nullptr;
                    if (!IUserTransaction::IsInUserTransaction(pDoc))
                    {
                        ut = IUserTransaction::Create(pDoc, GBMP_TR(L"修改构件属性"));
                        DBG_WARN_AND_RETURN_FALSE_UNLESS(ut, L"事务创建失败！", L"paramodel", L"2024-02-20");
                    }
                    param->SetParameterValueStorage(TransferOwnership(opCurrentParamValue));
                    std::wstring errorMsg;
                    if (pElement->GetElementParameters() && !pElement->GetElementParameters()->SetParameter(param, &errorMsg) && !errorMsg.empty())
                    {
                        if (ut)
                        {
                            ut->Rollback();
                        }
                        UiCommonDialog::ShowMessageBox(GBMP_TR(L"发生错误"), errorMsg, (int)UiCommonDialog::ButtonType::OK);
                        return false;
                    }
                    if (IInstanceType* instanceType = quick_cast<IInstanceType>(pElement))
                    {
                        IElementParameters* pParamBehavior = instanceType->GetElementParameters();
                        if (!pParamBehavior)
                            return false;

                        OwnerPtr<IParameter> nameParameter = pParamBehavior->GetParameterByUid(PARAMETER_UID(ElementNameBuiltInParameter));

                        IFamily* family = quick_cast<IFamily>(instanceType->GetFamily());
                        DBG_WARN_AND_RETURN_FALSE_UNLESS(family, L"获取不到Family", L"paramodel", L"2024-02-20");

                        IFamilyType* pFamilyType = family->GetFamilyTypeByName(nameParameter->GetValueAsString());
                        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyType, L"获取不到FamilyType", L"paramodel", L"2024-02-20");

                        // Type类型中，修改了类型参数，需要同时修改FamilyType中的参数值
                        pFamilyType->SetFamilyParameter(pElement->GetDocument(), param);
                    }
                    bParameterChanged = true;
                    return true;
                }
            }
        }
        return true;
    }

    bool SwitchTypeOfElement(IType* pNewType, IElement* pElement)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pNewType && pElement, L"invalid input arguments.",
            L"paramodel", L"2024-02-20");

        if (!pElement->GetBasicInformation())
            return false;

        IGenericType* pGenericType = quick_cast<IGenericType>(pNewType);
        IInstanceType* pInstanceType = quick_cast<IInstanceType>(pNewType);
        if (pGenericType)
        {

            if (pNewType->GetElementId() == pElement->GetBasicInformation()->GetTypeId())
                return false;

            bool changedSuccess = pElement->GetBasicInformation()->SetTypeId(pNewType->GetElementId());
            if (changedSuccess)
            {
                pElement->FinishEditing();
            }

            return changedSuccess;
        }
        else if (pInstanceType)
        {
            if (pNewType->GetElementId() == pElement->GetBasicInformation()->GetTypeId())
                return false;

            bool changedSuccess = false;
            IInstance* pInstance = quick_cast<IInstance>(pElement);
            if (pInstance && pInstance->ChangeTypeTo(pNewType->GetElementId()))
            {
                changedSuccess = true;
            }
            else if (pElement->GetBasicInformation()->SetTypeId(pNewType->GetElementId()))
            {
                changedSuccess = true;
            }

            if (changedSuccess)
            {
                //根据规则 重新设置参数
                pElement->FinishEditing();
            }

            return changedSuccess;
        }
        else
        {
            DBG_WARN_AND_RETURN_FALSE_UNLESS(false, L"invalid type.", L"paramodel", L"2024-02-20");
        }
    }

    bool CheckParameterValid(IDocument* pDoc, const gnuf::Item* pItem, const gcmp::IParameter* param, const IElement* pElement, const std::vector<gcmp::ElementId>& selElements)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"文档指针为空，不合法", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pItem, L"pItem is nullptr，不合法", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement, L"pElement is nullptr，不合法", L"paramodel", L"2024-02-20");

        bool isMultiValue = pItem->userData().cast<gfam::ItemInfo>().MultiValue;

        if (!pItem->enabled() || isMultiValue)
            return false;

        gnuf::EItemType eType = pItem->type();
        if (eType != gnuf::EItemType::eText && eType != gnuf::EItemType::eList)
        {
            return true;
        }

        if (eType != gnuf::EItemType::eList)
        {
            const IParameterDefinition* pParameterDefinition = param->GetParameterDefinition();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pParameterDefinition, L"pParameterDefinition为空", L"paramodel", L"2024-02-20");
            gcmp::ParameterStorageType storageTypes = pParameterDefinition->GetStorageType();
#pragma warning(push)
#pragma warning(disable: 4996)
            gcmp::ParameterDisplayType type = pParameterDefinition->GetDisplayType();
#pragma warning(pop)
            std::wstring strParamValue = L"";
            if (eType == gnuf::EItemType::eText)
            {
                const gnuf::Text* pText = pItem->cast<gnuf::Text>();
                if (pText)
                {
                    strParamValue = pText->text();
                }
            }
            else if (eType == gnuf::EItemType::eCheck)
            {
                const gnuf::Check* pCheck = pItem->cast<gnuf::Check>();
                if (pCheck)
                {
                    gnuf::CheckStatus boolCurValue = pCheck->checkState();
                    strParamValue = (boolCurValue != gnuf::CheckStatus::UnChecked);
                }
            }

            QString strValue = QString::fromStdWString(strParamValue).trimmed();
            bool isChecked = false;
            if (type == ParameterDisplayType::Angle)
            {
                int index = strValue.indexOf(QString::fromStdWString(GBMP_TR(L"°")));
                strValue = strValue.left(index);
                strValue.toDouble(&isChecked);
                if (!isChecked)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"请输入数值"), (int)UiCommonDialog::ButtonType::OK);
                    return false;
                }
            }
            else if (type == ParameterDisplayType::Slope)
            {
            }
            else if (type == ParameterDisplayType::Volume)
            {
            }
            else if (type == ParameterDisplayType::Area)
            {
            }
            else if (storageTypes == ParameterStorageType::Bool)
            {
                isChecked = (eType == gnuf::EItemType::eCheck);
                if (!isChecked)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"请输入布尔值"), (int)UiCommonDialog::ButtonType::OK);
                    return false;
                }
            }
            else if (storageTypes == ParameterStorageType::Int)
            {
                strValue.toInt(&isChecked);
                if (!isChecked)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"请输入整数"), (int)UiCommonDialog::ButtonType::OK);
                    return false;
                }
            }
            else if (storageTypes == ParameterStorageType::Double)
            {
                strValue.toDouble(&isChecked);
                if (!isChecked)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"请输入数值"), (int)UiCommonDialog::ButtonType::OK);
                    return false;
                }
            }

            //参数验证器只对值进行验证
            bool commitNow = false;
            OwnerPtr<IParameter> newParameter = param->Clone();
            OwnerPtr<IParameterValueStorage> opNewValStorge = nullptr;
            if (!GetCurrentParamValue(pDoc, param, pItem, selElements, opNewValStorge, commitNow))
            {
                return false;
            }

            newParameter->SetParameterValueStorage(TransferOwnership(opNewValStorge));
            //没有验证器，默认为合法
            const IParameterValidator* pValidator = newParameter->GetValidator();
            if (!pValidator)
                return true;

            std::wstring errorMessage;
            bool validateResult = pValidator->Validate(newParameter.get(), pElement, &errorMessage);
            if (!validateResult && !errorMessage.empty())
            {
                UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(errorMessage), (int)UiCommonDialog::ButtonType::OK);
                return false;
            }
        }

        return true;
    }

    bool NotifyFinishEvent(const std::wstring& eventTypeId, const std::wstring& newValue)
    {
        gfam::GnufPropertyPallet* propertyPallet = gfam::GnufPropertyPallet::Get();
        if (!propertyPallet)
            return false;
        if (propertyPallet->GetPreSetElementId().IsValid())
            return false;
        gfam::PropertyPanelEventArgs inputArgs(eventTypeId, newValue);
        inputArgs.SetPropertyItemUniqueId(propertyPallet->GetComponentTypeChangedEventId());
        gfam::GnufPropertyPanelEvent* panelEvent = dynamic_cast<gfam::GnufPropertyPanelEvent*>(propertyPallet->GetInputFinishedEvent());
        if (!panelEvent)
            return false;
        panelEvent->Emit(&inputArgs);
        return true;
    }

    //发送属性参数变化事件，在CheckLeaveEventHandler后是为了确保修改属性面板的事务已经提交
    bool NotifyAfterParameterChanged(const gnuf::Item* pItem)
    {
        if (!pItem)
            return false;
        gfam::GnufPropertyPallet* propertyPalette = gfam::GnufPropertyPallet::Get();
        if (!propertyPalette)
            return false;
        gfam::PropertyPanelEventArgs args(STR_FAM_EVENT_TYPE_CHANGE_PROPERTY_VALUE, L"");
        args.SetPropertyItemUniqueId(StringUtil::ToWString(pItem->userData().cast<gfam::ItemInfo>().ParamId));
        gfam::GnufPropertyPanelEvent* panelEvent = dynamic_cast<gfam::GnufPropertyPanelEvent*>(propertyPalette->GetInputEvent());
        if (!panelEvent)
            return false;
        panelEvent->Emit(&args);
        return true;
    }

    bool UpdateItemMultiValue(gnuf::Item* pItem, bool isMultiValue)
    {
        if (!pItem)
            return false;

        gfam::ItemInfo info = pItem->userData().cast<gfam::ItemInfo>();
        info.MultiValue = isMultiValue;
        pItem->setUserData(info);

        if (gnuf::List * pList = pItem->cast<gnuf::List>())
        {
            gfam::GnufPropertyPallet* propertyPallet = gfam::GnufPropertyPallet::Get();
            if (!propertyPallet)
                return false;

            gfam::PropertyPanelEventArgs args(STR_FAM_EVENT_TYPE_CLICK_PROPERTY_ITEM_BUTTON, pList->Text());
            args.SetPropertyItemUniqueId(StringUtil::ToWString(info.ParamId));
            gfam::GnufPropertyPanelEvent* panelEvent = dynamic_cast<gfam::GnufPropertyPanelEvent*>(propertyPallet->GetInputEvent());
            if (!panelEvent)
                return false;
            panelEvent->Emit(&args);
        }
        return true;
    }

    bool IsCurModelViewShow(const std::vector<ElementId>& selElements)
    {
        if (selElements.size() != 1)
            return false;

        if (IUiDocumentViewManager::Get() == nullptr)
            return false;

        IUiView* pUIView = IUiDocumentViewManager::Get()->GetCurrentUiView();
        if (pUIView == nullptr)
            return false;

        IModelView* pModelView = pUIView->GetModelView();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView != nullptr, L"pModelView不能为空", L"paramodel", L"2024-02-20");

        DBG_WARN_AND_RETURN_FALSE_UNLESS(pModelView->GetBasicInformation() != nullptr, L"pModelView->GetBasicInformation()不能为空", L"paramodel", L"2024-02-20");
        bool isCurView = pModelView->GetBasicInformation()->GetElementId() == selElements[0];
        return isCurView;
    }

    bool InputNameIsValid(const IType* pType, const std::wstring& name)
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pType, L"pType为空", L"paramodel", L"2024-02-20");
        const IDocument* pDoc = pType->GetDocument();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"当前文档为空", L"paramodel", L"2024-02-20");

        const IInstanceType* pInstanceType = quick_cast<IInstanceType>(pType);
        if (pInstanceType != nullptr)
        {
            std::vector<const IFamilyType*> fmTypes;
            if (pInstanceType->IsSub())
            {
                IFamily* pTopFamily = quick_cast<IFamily> (pDoc->GetElement(pInstanceType->GetTopFamilyId()));
                DBG_WARN_AND_RETURN_UNLESS(pTopFamily != nullptr, false, L"pFamily为空！", L"paramodel", L"2024-02-20");
                fmTypes = pTopFamily->GetAllSubFamilyTypesBySubInstanceType(pInstanceType);
            }
            else
            {
                IFamily* pFamily = pInstanceType->GetFamily();
                DBG_WARN_AND_RETURN_UNLESS(pFamily != nullptr, false, L"pFamily为空！", L"paramodel", L"2024-02-20");
                fmTypes = pFamily->GetFamilyTypes();
            }
            FOR_EACH(type, fmTypes)
            {
                if (name == type->GetName())
                {
                    return false;
                }
            }
            return true;
        }

        const IElementBasicInformation* pElementBasicInformation = pType->GetBasicInformation();
        DBG_WARN_AND_RETURN_UNLESS(pElementBasicInformation, false, L"获取BasicInformation失败", L"paramodel", L"2024-02-20");
        std::vector<IElement*> allElements = pDoc->GetElementsByCategory(pElementBasicInformation->GetCategoryUid());
        FOR_EACH(ele, allElements)
        {
            if (ele->GetBasicInformation() && name == ele->GetBasicInformation()->GetName())
            {
                return false;
            }
        }
        return true;
    }

    bool addPropertyGroup(gnuf::NameValuePairs* nameValuePairs, const std::wstring& propertyGroup)
    {
        gnuf::NameValuePairBlock* nvpb = nameValuePairs->addNameValuePairBlock(Info(propertyGroup), true);
        return nvpb != nullptr;
    }

    gnuf::NameValuePairBlock*  hasPropertyGroup(gnuf::NameValuePairs* nameValuePairs, const std::wstring& propertyGroup)
    {
        if (!nameValuePairs)
            return nullptr;
        gnuf::NameValuePairBlock* nvpb = nullptr;
        gnuf::NameValuePairs::RawContents blocks = nameValuePairs->rawContents();
        FOR_EACH(block, blocks)
        {
            nvpb = block->cast<gnuf::NameValuePairBlock>();
            if (!nvpb)
                continue;
            const gnuf::Info* info = nvpb->info();
            if (!info)
                continue;
            if (info->caption() == propertyGroup)
                break;
        }
        return nvpb;
    }

    //已知所属分组情况下查找属性值
    gnuf::Item* hasPropertyItem(gnuf::NameValuePairs* nameValuePairs, const std::wstring& propertyGroup, const std::wstring& propertyValue)
    {
        gnuf::NameValuePairBlock* nvpb = hasPropertyGroup(nameValuePairs, propertyGroup);

        if (!nvpb)
            return nullptr;

        gnuf::NameValuePairBlock::RawContents valuePairs = nvpb->rawContents();
        if (valuePairs.empty())
            return nullptr;
        FOR_EACH(valuePair, valuePairs)
        {
            if (!valuePair)
                continue;

            const gnuf::Info* info = valuePair->info();
            if (!info)
                continue;
            if (info->caption() == propertyValue && valuePair->cast<gnuf::NameValuePair>())
                return valuePair->cast<gnuf::NameValuePair>()->value();
        }

        return nullptr;
    }

    static bool IsConnectorParameterModifiable(const IElementParameters* pElementParameters, const UniIdentity& paramUid, const UniIdentity& paramDefUid1, const UniIdentity& paramDefUid2)
    {
        if (paramDefUid2 != paramDefUid1 && paramDefUid1 != paramUid)
            return true;

        if (OwnerPtr<IParameter> paramDef = pElementParameters->GetParameterByUid(paramDefUid1))
        {
            if (!pElementParameters->IsParameterModifiable(paramDef->GetParameterDefinitionId()))
            {
                return false;
            }
        }

        if (OwnerPtr<IParameter> paramDef = pElementParameters->GetParameterByUid(paramDefUid2))
        {
            if (!pElementParameters->IsParameterModifiable(paramDef->GetParameterDefinitionId()))
            {
                return false;
            }
        }

        return true;
    }

    // 判断参数是否可修改和绑定
    static std::pair<bool, bool> GetParameterCanModifyAndBind(const IElement* pElement, const IParameter* pParameter)
    {
        std::pair<bool, bool> disableResult = {false, false};
        DBG_WARN_AND_RETURN_UNLESS(pParameter, disableResult, L"pParameter为空？", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_UNLESS(pElement, disableResult, L"pElement为空？", L"paramodel", L"2024-02-20");

        IDocument* pDocument = pElement->GetDocument();
        DBG_WARN_AND_RETURN_UNLESS(pDocument, disableResult, L"pDocument为空？", L"paramodel", L"2024-02-20");

        if (pDocument->IsReadonlyForSharingViolation())
        {
            return disableResult;
        }

        ParameterProcessType processType = pParameter->GetParameterProcessType();

        if (processType == ParameterProcessType::GeneralOutput)
        {
            return disableResult;
        }
        else if (processType == ParameterProcessType::Bound)
        {
            return std::pair<bool, bool>{false, true};
        }

        std::pair<bool, bool > readonly{false, pParameter->IsBindable()};

        if (const IElementParameters* pElementParameters = pElement->GetElementParameters())
        {

            if (!pElementParameters->IsParameterModifiable(pParameter->GetParameterDefinitionId()))
            {
                return readonly;
            }
        }

        if (!pParameter->IsModifiable())
        {
            return readonly;
        }

        if (quick_cast<const IInstanceType>(pElement))
        {
            return std::pair<bool, bool>{true, pParameter->IsBindable() || pParameter->IsDriveParameter()};
        }

        return std::pair<bool, bool>{true, pParameter->IsBindable()};
    }

    static int FindListSelectIndex(const std::vector<OwnerPtr<Info>>& infos, const std::wstring & text)
    {
        int count = static_cast<int>(infos.size());
        for (int i = 0; i < count; ++i)
        {
            if (infos[i]->caption() == text)
            {
                return i;
            }
        }

        return -1;
    }


}

gfam::QtGnufPropertyPallet* qtGnufPropertyPallet()
{
    gfam::GnufPropertyPallet* pPropertyPallet = gfam::GnufPropertyPallet::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPropertyPallet, L"pPropertyPallet为空!", L"paramodel", L"2024-02-20");
    gfam::QtGnufPropertyPallet* qtWidget = pPropertyPallet->GetQtGnufPropertyPallet();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(qtWidget, L"qtWidget为空!", L"paramodel", L"2024-02-20");
    return qtWidget;
}

gnuf::Item* AddPropertyItemToBlock(gcmp::IDocument* pDocument, gnuf::NameValuePairBlock* pBlock, const gcmp::IParameter& param, gcmp::ElementId elementId, const std::vector<gcmp::ElementId>& elementIds, int parameterId, bool isMultiValue, bool isReadOnly, bool bCanBeBind)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDocument, L"pDocument为空", L"paramodel", L"2024-02-20");

    const IParameterDefinition* pParamDefinition = param.GetParameterDefinition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParamDefinition, L"pParamDefinition为空", L"paramodel", L"2024-02-20");

    //链接对象的参数所属的Document不是当前Document,直接通过当前Document去获取参数的一些原始数据会有误
    const IDocument* pDocumentParamBelong = pDocument;
    if (param.GetDocument() != pDocument
        && !elementIds.empty())
    {
        const ILinkElementProxy *pLinkElementProxy = quick_cast<ILinkElementProxy>(pDocument->GetElement(elementIds[0]));
        if (pLinkElementProxy)
        {
            pDocumentParamBelong = param.GetDocument();
        }
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDocumentParamBelong, L"pDocumentParamBelong为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParamDefinition->IsValidParameterDefinition(pDocumentParamBelong), L"pParamDefinition无效", L"paramodel", L"2024-02-20");

    IParameterDisplayManager* pParamDisplayMgr = IParameterDisplayManager::Get(pDocumentParamBelong);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParamDisplayMgr, L"pParamDisplayMgr为空!", L"paramodel", L"2024-02-20");

    const IParameterDisplay* parameterDisplay = pParamDisplayMgr->GetParameterDisplay(pParamDefinition->GetUid());
    const std::wstring parameterName = param.GetName();

    gnuf::ButtonEx* pBtn = nullptr;
    gnuf::Item* parentItem = nullptr;
    gnuf::Item* pItem = gfam::IGnufParameterDisplayCustom::FindItemInCurrentBlock(pBlock, parameterId);
    if (const IParameterDisplayDropdownList* dropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(parameterDisplay))
    {
        gnuf::List* pList = nullptr;
        if (pList == nullptr)
        {
            if (bCanBeBind)
            {
                gnuf::Block* childBlock = pBlock->addItem<Block>(Info(parameterName));
                DBG_WARN_AND_RETURN_NULLPTR_UNLESS(childBlock, L"childBlock为空", L"paramodel", L"2024-02-20");
                pList = childBlock->addItem<List>();
                pBtn = childBlock->addItem<PushButton>();
                gcmp::OwnerPtr<gnuf::ButtonAppearanceSetting> btnSetting = NEW_AS_OWNER_PTR(gnuf::ButtonAppearanceSetting);
                btnSetting->setWidth(30);
                btnSetting->setHeight(30);
                pBtn->assignCustomizeAppearanceSetting(TransferOwnership(btnSetting));
                pItem = pList;
                parentItem = childBlock;
            }
            else
            {
                pList = pBlock->addItem<List>(Info(parameterName));
                pItem = pList;
            }
        }
        else
        {
            if (pItem->type() == gnuf::EItemType::eList)
            {
                pList = pItem->cast<gnuf::List>();
                pItem = pList;
            }
            else if (pItem->type() == gnuf::EItemType::eBlock)
            {
                gnuf::Block* childBlock = pItem->cast<gnuf::Block>();
                gnuf::Item* firstItem = childBlock->rawContents()[0];
                if (firstItem->type() == gnuf::EItemType::eList)
                {
                    pList = firstItem->cast<gnuf::List>();
                }

                pItem = pList;
                parentItem = childBlock;
            }
        }

        //gnuf::List* pList = pItem == nullptr ? pBlock->addList(NEW_AS_OWNER_PTR(gnuf::Info, parameterName)) : pItem->cast<gnuf::List>();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pList, L"pList is nullptr", L"paramodel", L"2024-02-20");
        pList->ClearItem();
        std::vector<std::wstring>  displayStrings = dropdownList->GetDisplayStrings(pDocument, elementIds);
        auto iter = std::find(displayStrings.begin(), displayStrings.end(), ParameterDisplayUtils::GetValueAsDisplayString(&param));
        bool isSpecial = false;
        if (iter == displayStrings.end())
        {
            //对于关联平面 顶部标高 定位表面 如果构件放到普通面上 属性值需要特殊处理 
            std::vector<std::wstring> needProcessProperpNames = { GBMP_TR(L"关联平面"),GBMP_TR(L"顶部标高"),GBMP_TR(L"定位表面") };
            iter = std::find(needProcessProperpNames.begin(), needProcessProperpNames.end(), param.GetName());
            if (iter != needProcessProperpNames.end())
            {
                //需要加上 如果不加 平台后边会检查出在属性值下拉列表中找不到当前值 默认会显示成第一个
                displayStrings.push_back(param.GetName());
                //按照需求 此时灰显
                pList->setEnabled(false);
                isSpecial = true;
            }
        }
        std::wstring paramDisplayStr = dropdownList->GetDisplayStringByValue(pDocument, param.GetParameterValueStorage());
        if (!paramDisplayStr.empty() && (std::find(displayStrings.begin(), displayStrings.end(), paramDisplayStr) == displayStrings.end()))
        {
            displayStrings.push_back(paramDisplayStr);
        }
        if (isMultiValue)
        {
            displayStrings.push_back(multiValueText);
            paramDisplayStr = multiValueText;
        }
        if (paramDisplayStr.empty())
        {
            displayStrings.push_back(emptyValueText);
            paramDisplayStr = emptyValueText;
        }
        int selectedIndex = 0;
        FOR_EACH_INDEX(index, displayStrings)
        {
            pList->AddItem(NEW_AS_OWNER_PTR(gnuf::Info, displayStrings[index]));
            if (displayStrings[index] == paramDisplayStr)
            {
                selectedIndex = index;
            }
        }
        pList->SetSelectedIndex(selectedIndex);
        if (PARAMETER_TYPE(Material) == pParamDefinition->GetParameterTypeId())
        {
            // 备份选择索引，方便恢复上一次选择的值
            pList->setUserData(Any(selectedIndex));
        }

        if (!isSpecial)
        {
            pList->setEnabled(!isReadOnly);
        }
    }
    else if (const IParameterDisplayEditbox* editbox = dynamic_cast<const IParameterDisplayEditbox*>(parameterDisplay))
    {
        gnuf::Text* pText = nullptr;
        if (nullptr == pItem)
        {
            if (bCanBeBind)
            {
                gnuf::Block* childBlock = pBlock->addItem<Block>(Info(parameterName));
                DBG_WARN_AND_RETURN_NULLPTR_UNLESS(childBlock, L"childBlock为空", L"paramodel", L"2024-02-20");
                pText = childBlock->addItem<Text>();
                pBtn = childBlock->addItem<PushButton>();
                gcmp::OwnerPtr<gnuf::ButtonAppearanceSetting> btnSetting = NEW_AS_OWNER_PTR(gnuf::ButtonAppearanceSetting);
                btnSetting->setWidth(30);
                btnSetting->setHeight(30);
                pBtn->assignCustomizeAppearanceSetting(TransferOwnership(btnSetting));
                pItem = pText;
                parentItem = childBlock;
            }
            else
            {
                pText = pBlock->addItem<Text>(Info(parameterName));
                pItem = pText;
            }
        }
        else
        {
            if (pItem->type() == gnuf::EItemType::eText)
            {
                pText = pItem->cast<gnuf::Text>();
                pItem = pText;
            }
            else if (pItem->type() == gnuf::EItemType::eBlock)
            {
                gnuf::Block* childBlock = pItem->cast<gnuf::Block>();
                DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!childBlock->rawContents().empty(), L"childBlock->rawContents()为空", L"paramodel", L"2024-02-20");
                gnuf::Item* firstItem = childBlock->rawContents()[0];
                if (firstItem && firstItem->type() == gnuf::EItemType::eText)
                {
                    pText = firstItem->cast<gnuf::Text>();
                }

                pItem = pText;
                parentItem = childBlock;
            }            
        }

        std::wstring paramDisplayStr = ParameterDisplayUtils::GetValueAsDisplayString(&param);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!pText, L"pText为空", L"paramodel", L"2024-02-20");
        pText->setText(isMultiValue ? multiValueText : paramDisplayStr);
        pText->setReadonly(isReadOnly);
    }
    else if (const IParameterDisplayEditboxWithButton* editbox = dynamic_cast<const IParameterDisplayEditboxWithButton*>(parameterDisplay))
    {
        gnuf::Text* pText = nullptr;
        if (nullptr == pItem)
        {
            if (bCanBeBind)
            {
                gnuf::Block* childBlock = pBlock->addItem<Block>(Info(parameterName));
                DBG_WARN_AND_RETURN_NULLPTR_UNLESS(childBlock, L"childBlock为空", L"paramodel", L"2024-02-20");
                pText = childBlock->addItem<Text>();
                pBtn = childBlock->addItem<PushButton>();
                gcmp::OwnerPtr<gnuf::ButtonAppearanceSetting> btnSetting = NEW_AS_OWNER_PTR(gnuf::ButtonAppearanceSetting);
                btnSetting->setWidth(30);
                btnSetting->setHeight(30);
                pBtn->assignCustomizeAppearanceSetting(TransferOwnership(btnSetting));
                pItem = pText;
                parentItem = childBlock;
            }
            else
            {
                pText = pBlock->addItem<Text>(Info(parameterName));
                pItem = pText;
            }
        }
        else
        {
            if (pItem->type() == gnuf::EItemType::eText)
            {
                pText = pItem->cast<gnuf::Text>();
                pItem = pText;
            }
            else if (pItem->type() == gnuf::EItemType::eBlock)
            {
                gnuf::Block* childBlock = pItem->cast<gnuf::Block>();
                gnuf::Item* firstItem = childBlock->rawContents()[0];
                if (firstItem->type() == gnuf::EItemType::eText)
                {
                    pText = firstItem->cast<gnuf::Text>();
                }

                pItem = pText;
                parentItem = childBlock;
            }
        }

        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pText, L"pText is nullptr", L"paramodel", L"2024-02-20");
        if (isMultiValue)
        {
            pText->setText(L"");
        }
        else
        {
            std::wstring paramDisplayStr = ParameterDisplayUtils::GetValueAsDisplayString(&param);
            pText->setText(paramDisplayStr);
        }
        pText->setReadonly(isReadOnly);
    }
    else if (const IParameterDisplayCheckbox* checkbox = dynamic_cast<const IParameterDisplayCheckbox*>(parameterDisplay))
    {
        gnuf::Check* pCheck = nullptr;
        if (nullptr == pItem)
        {
            if (bCanBeBind)
            {
                gnuf::Block* childBlock = pBlock->addItem<Block>(Info(parameterName));
                DBG_WARN_AND_RETURN_NULLPTR_UNLESS(childBlock, L"childBlock为空", L"paramodel", L"2024-02-20");
                pCheck = childBlock->addItem<Check>();
                pBtn = childBlock->addItem<PushButton>();
                gcmp::OwnerPtr<gnuf::ButtonAppearanceSetting> btnSetting = NEW_AS_OWNER_PTR(gnuf::ButtonAppearanceSetting);
                btnSetting->setWidth(30);
                btnSetting->setHeight(30);
                pBtn->assignCustomizeAppearanceSetting(TransferOwnership(btnSetting));
                pItem = pCheck;
                parentItem = childBlock;
            }
            else
            {
                pCheck = pBlock->addItem<Check>(Info(parameterName));
                pItem = pCheck;
            }
        }
        else
        {
            if (pItem->type() == gnuf::EItemType::eCheck)
            {
                pCheck = pItem->cast<gnuf::Check>();
                pItem = pCheck;
            }
            else if (pItem->type() == gnuf::EItemType::eBlock)
            {
                gnuf::Block* childBlock = pItem->cast<gnuf::Block>();
                gnuf::Item* firstItem = childBlock->rawContents()[0];
                if (firstItem->type() == gnuf::EItemType::eCheck)
                {
                    pCheck = firstItem->cast<gnuf::Check>();
                }

                pItem = pCheck;
                parentItem = childBlock;
            }
        }

        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!pCheck, L"pCheck为空", L"paramodel", L"2024-02-20");
        pCheck->setCheckState(isMultiValue ? gnuf::CheckStatus::PartiallyChecked :
            (param.GetValueAsBool() ? gnuf::CheckStatus::Checked : gnuf::CheckStatus::UnChecked));

        pCheck->setEnabled(!isReadOnly);
    }
    else if (gfam::IGnufParameterDisplayCustom* pDisplayCustom = gfam::GnufParameterDisplayCustomFactory::Get()->Find(pParamDefinition->GetUid()))
    {
        const size_t num = elementIds.size();
        std::vector<gcmp::IElement *> elements(num, nullptr);
        for (int i = 0; i < num; ++i) {
            gcmp::ElementId elemId = elementIds[i];
            elements[i] = pDocument->GetElement(elemId);
            // 获取多选时控件的使能状态
            const IElementParameters* pParameter = elements[i]->GetElementParameters();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pParameter, L"pParameter为空", L"paramodel", L"2024-02-20");
            OwnerPtr<IParameter> opParameter = pParameter->GetParameterById(parameterId);
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opParameter, L"opParameter为空", L"paramodel", L"2024-02-20");
            if (!opParameter->IsModifiable())
            {
                isReadOnly = true;
            }
        }

        if (pItem == nullptr)
        {
            if (isMultiValue)
            {
                pItem = pDisplayCustom->OnDisplay(pBlock, elements, pParamDefinition->GetId());
            }

            if (nullptr == pItem)
            {
                pItem = pDisplayCustom->OnDisplay(pBlock, pDocument->GetElement(elementId), pParamDefinition->GetId());
            }
        }
        if (pItem)
        {
            pItem->setEnabled(!isReadOnly);
        }
    }
    else
    {
        if (!parameterDisplay)
            return nullptr;
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"未知类型的ParameterDisplay", L"paramodel", L"2024-02-20");
    }

    if (pItem)
    {
        gfam::ItemInfo pInfo(elementId, isMultiValue, parameterId);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pItem->parent()&&pBlock->info(), L"pItem->parent()&& pBlock->info()为空", L"paramodel", L"2024-02-20");
        pItem->setQtObjectName(StringUtil::ToWString(pItem->parent()->path().str()) + L"/" + pBlock->info()->caption() + L"$" + parameterName);
        pItem->setUserData(gcmp::Any(pInfo));

        if (parentItem)
        {
            parentItem->setUserData(gcmp::Any(pInfo));
        }

        if (pBtn)
        {
            pBtn->setUserData(gcmp::Any(pInfo));
        }
    }
    if (pBtn != nullptr)
    {
        pBtn->assignInfo(gnuf::Info(L"", L"", L":/images/ModelView/PropertiesPanel/AssociateParameters"));
        gcmp::OwnerPtr<gnuf::ButtonAppearanceSetting> btnSetting = NEW_AS_OWNER_PTR(gnuf::ButtonAppearanceSetting);
        if (btnSetting)
        {
            btnSetting->setBackgroundColor(255, 255, 255);
            btnSetting->setPressedColor(0, 0, 0);
            btnSetting->setHoverColor(100, 100, 100);
            pBtn->assignCustomizeAppearanceSetting(TransferOwnership(btnSetting));
        }
    }
    return pItem;
}

void gfam::PropertyNameValuePairsComponent::BuildNameValuePairs(bool rebuild, bool fromElements)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pNameValuePairs, L"pNameValuePairs is nullptr", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpDoc, L"m_wpDoc is nullptr", L"paramodel", L"2024-02-20");

    if (rebuild)
    {
        m_pNameValuePairs->clearContents();
    }

    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_elementIds.empty(), L"m_elementIds is empty", L"paramodel", L"2024-02-20");
    const IElement* pElement = m_wpDoc->GetElement(m_elementIds[0]);
    if (!pElement)
    {
        return;
    }

    std::map<int, bool> paramDefIdToIsParamMultiVals;

    if (fromElements)
    {
        std::vector<OwnerPtr<IParameter>> commonParams;
        std::vector<bool> paramMultiVals;
        GetCommonParameters(m_wpDoc.Get(), pElement, m_elementIds, commonParams, paramMultiVals);

        // 参数分组、排序
        GroupNameParametersArray finalOutGroupParameters;
        GroupAndSortParameters(pElement, m_elementIds, commonParams, paramMultiVals, finalOutGroupParameters, paramDefIdToIsParamMultiVals);
        m_parametersArray = std::move(finalOutGroupParameters); //面板组别
    }

    // 创建参数组
    int groupId = 0;
    bool isCurView = IsCurModelViewShow(m_elementIds);
    const IParameterDefinitionLibrary* pParamDefLib = IParameterDefinitionLibrary::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDefLib != nullptr, L"pParamDefLib为空", L"paramodel", L"2024-02-20");
    const int elementNameParamDefId = pParamDefLib->GetParameterDefinitionIdByUid(PARAMETER_UID(ElementNameBuiltInParameter));

    //记录顶部标高和高度
    gnuf::Item* pTopElevationItem = nullptr;
    gnuf::Item* pHeightItem = nullptr;
    gnuf::Item* pTurnLeftRightItem = nullptr;
    gnuf::Item* pTurnInnerOuterItem = nullptr;
    int topElevationParamDefId = -1;
    FOR_EACH(curParamGroupItem, m_parametersArray)//按组循环
    {
        // 添加参数分组
        //注意：groupId < 0 ,(控件内部只用一个容器存放，防止与属性项ID重叠)
        const std::wstring& curGroupName = curParamGroupItem.first;
        const std::vector<OwnerPtr<IParameter>>& curGroupParams = curParamGroupItem.second;

        // 如果组内参数为空，则不显示空组
        if (curGroupParams.empty())
            continue;

        gnuf::NameValuePairBlock* nvpb = nullptr;
        if (!rebuild)
        {
            gnuf::NameValuePairs::RawContents nameValueContents = m_pNameValuePairs->rawContents();
            FOR_EACH(content, nameValueContents)
            {
                if (gnuf::NameValuePairBlock* pBlock = content->cast<gnuf::NameValuePairBlock>())
                {
                    if (pBlock->info() && pBlock->info()->caption() == curGroupName)
                    {
                        nvpb = pBlock;
                        break;
                    }
                }
            }
        }
        if (!nvpb)
        {
            nvpb = m_pNameValuePairs->addNameValuePairBlock(Info(curGroupName), true);
        }
        DBG_WARN_AND_CONTINUE_UNLESS(nvpb, L"nvpb is nullptr", L"paramodel", L"2024-02-20");

        // 添加分组下的所有参数
        for (int loop = 0; loop < (int)curGroupParams.size(); ++loop)//组内参数循环处理
        {
            const IParameter* curParam = curGroupParams[loop].get();
            if (curParam == nullptr || !curParam->IsUserVisible())
            {
                continue;
            }
            int curParamDefId = curParam->GetParameterDefinitionId();
            const IParameterDefinition* pCurParamDef = curParam->GetParameterDefinition();
            DBG_WARN_AND_CONTINUE_UNLESS(pCurParamDef, L"通过参数获取的参数定义指针为空，不合法", L"paramodel", L"2024-02-20");
            std::wstring originParamName = pCurParamDef->GetName();
            std::wstring paramName;
            if (originParamName == GBMP_TR(L"底部偏移"))
            {
                paramName = curParam->GetName();
            }
            std::wstring paramValue = ParameterDisplayUtils::GetValueAsDisplayString(curParam);

            // 特殊处理-“视图名称”属性
            bool isNameParam = (curParamDefId == elementNameParamDefId);
            if (isCurView && isNameParam)
            {
                paramName = GBMP_TR(L"视图名称");
                paramValue = curParam->GetValueAsString();
            }

            // 预设参数
            if (m_tmpPreSetElementId.IsValid())
            {
                const IElementParameters* pElementParameters = pElement->GetElementParameters();
                if (pElementParameters &&
                    !pElementParameters->IsPresetParameter(pCurParamDef->GetUid()))
                {
                    continue;
                }
            }


            auto modifyAndBindStatus = GetParameterCanModifyAndBind(pElement, curParam);


            gnuf::Item* pItem = AddPropertyItemToBlock(m_wpDoc.Get(), nvpb, *curParam, m_elementIds[0], m_elementIds, curParamDefId, paramDefIdToIsParamMultiVals[curParamDefId], !modifyAndBindStatus.first, modifyAndBindStatus.second);

            if (curParam->GetName() == GBMP_TR(L"顶部标高"))
            {
                pTopElevationItem = pItem;
                topElevationParamDefId = curParamDefId;
            }
            if (curParam->GetName() == GBMP_TR(L"高度"))
            {
                pHeightItem = pItem;
            }
            if (curParam->GetName() == GBMP_TR(L"翻转左右"))
            {
                pTurnLeftRightItem = pItem;
            }
            if (curParam->GetName() == GBMP_TR(L"翻转内外"))
            {
                pTurnInnerOuterItem = pItem;
            }
        }
    }

    if (pHeightItem && pTopElevationItem && topElevationParamDefId != -1 && paramDefIdToIsParamMultiVals[topElevationParamDefId])
    {
        pHeightItem->setEnabled(false);
    }

    if (pTurnLeftRightItem)
    {
        if (pElement && pElement->GetBasicInformation() && pElement->GetBasicInformation()->GetIsTransient())
        {
            pTurnLeftRightItem->setEnabled(false);
        }
        else
        {
            pTurnLeftRightItem->setEnabled(true);
        }
    }
    if (pTurnInnerOuterItem)
    {
        if (pElement && pElement->GetBasicInformation() && pElement->GetBasicInformation()->GetIsTransient())
        {
            pTurnInnerOuterItem->setEnabled(false);
        }
        else
        {
            pTurnInnerOuterItem->setEnabled(true);
        }
    }

    m_pNameValuePairs->eraseEmptyNameValuePairBlocks();
    m_pNameValuePairs->dumpContents();

}

void gfam::PropertyNameValuePairsComponent::SetDocument(gcmp::IDocument * pDoc)
{
    m_wpDoc = pDoc;
}

void gfam::PropertyNameValuePairsComponent::GetCommonParameters(gcmp::IDocument * pDoc, const gcmp::IElement * pEle, const std::vector<gcmp::ElementId>& selElements, std::vector<gcmp::OwnerPtr<gcmp::IParameter>>& params, std::vector<bool>& paramMultiVals)
{
    //先根据参数类型找到公共参数
    std::vector<int> paramDefs;
    std::vector<IElement*> otherSelEles;
    const IElementParameters* pElementParameters = pEle->GetElementParameters();
    if (pElementParameters)
        pElementParameters->ReportParameterDefinitions(&paramDefs);

    // 参数去重
    {
        std::vector<int> paramDefsNoDup;
        FOR_EACH(tmpParamId, paramDefs)
        {
            if (std::find(paramDefsNoDup.begin(), paramDefsNoDup.end(), tmpParamId) == paramDefsNoDup.end())
                paramDefsNoDup.push_back(tmpParamId);
        }

        paramDefs.swap(paramDefsNoDup);
    }

    for (int i = 1; i < (int)selElements.size(); ++i)
    {
        IElement* pSelEle = pDoc->GetElement(selElements[i]);
        //wangqy-b 组合体对象完成增量更新前直接返回
        if (!pSelEle)
            return;
        DBG_WARN_AND_RETURN_VOID_UNLESS(pSelEle != nullptr, L"pSelEle为空", L"paramodel", L"2024-02-20");
        otherSelEles.push_back(pSelEle);

        std::vector<int> otherSelParams;
        IElementParameters* pElementParameters1 = pSelEle->GetElementParameters();
        if (pElementParameters1)
            pElementParameters1->ReportParameterDefinitions(&otherSelParams);
        for (auto itr = paramDefs.begin(); itr != paramDefs.end(); )
        {
            if (std::find(otherSelParams.begin(), otherSelParams.end(), *itr) == otherSelParams.end())
            {
                itr = paramDefs.erase(itr);
            }
            else
            {
                ++itr;
            }
        }
    }

    bool isCurViewShow = IsCurModelViewShow(selElements);
    //根据值是否相同判断是否多值,有对象不显示该参数，公共也不显示。
    FOR_EACH(paramDefItem, paramDefs)
    {
        OwnerPtr<IParameter> curParam;
        if (pElementParameters)
            curParam = pElementParameters->GetParameterById(paramDefItem);
        if (!curParam)
            continue;

        gcmp::IParameterDefinitionLibrary* paramDefinitionLibrary = gcmp::IParameterDefinitionLibrary::Get(pDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(paramDefinitionLibrary, L"paramDefinitionLibrary为空", L"paramodel", L"2024-02-20");
        // Instance处理 隐藏由表达式驱动的参数
        const IInstance *instance = quick_cast<IInstance>(pEle);
        if (instance)
        {
            if (curParam->IsDriveParameter()&&
                curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(BottomOffsetBuiltInParameter))
                && curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(IsVisiableInParentDocumentBuiltInParameter))
                && curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(VisibilityFlagBuiltInParameter))
                && curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(AssociatedPlaneBuiltInParameter))
                && curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(ElementNameBuiltInParameter))
                && curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(FamFormIsSubstractionBodyBuiltInParameter))
                && curParam->GetParameterDefinitionId() != paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(MaterialDisplayStyleBuiltInParameter)))
            {
                curParam->SetBindable(true);
            }
        }

        const IParameterDefinition* pParameterDefinition = curParam->GetParameterDefinition();
        DBG_WARN_AND_CONTINUE_UNLESS(pParameterDefinition, L"pParameterDefinition为空", L"paramodel", L"2024-02-20");
        if (!isCurViewShow && (pParameterDefinition->GetParameterTypeId() == PARAMETER_TYPE(None))) //当前参数不显示
            continue;

        bool isDisplay = true;
        bool isMultiValue = false;
        for (auto itr = otherSelEles.begin(); itr != otherSelEles.end(); ++itr)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(*itr, L"*itr为空", L"paramodel", L"2024-02-20");

            OwnerPtr<IParameter> otherParam;
            if ((*itr)->GetElementParameters())
                otherParam = (*itr)->GetElementParameters()->GetParameterById(paramDefItem);

            if (!otherParam)
            {
                isDisplay = false;
                break;
            }
            DBG_WARN_AND_CONTINUE_UNLESS(otherParam->GetParameterDefinition(), L"otherParam->GetParameterDefinition()为空", L"paramodel", L"2024-02-20");

            if (otherParam->GetParameterDefinition()->GetParameterTypeId() == PARAMETER_TYPE(None))//当前参数不显示
            {
                isDisplay = false;
                break;
            }

            DBG_WARN_AND_CONTINUE_UNLESS(otherParam->GetParameterValueStorage(), L"otherParam->GetParameterValueStorage为空", L"paramodel", L"2024-02-20");
            DBG_WARN_AND_CONTINUE_UNLESS(curParam->GetParameterValueStorage(), L"curParam->GetParameterValueStorage()为空", L"paramodel", L"2024-02-20");
            if (isMultiValue == false && curParam->GetParameterValueStorage()->HasSameValue(otherParam->GetParameterValueStorage()) == false)
            {
                isMultiValue = true;
                break;
            }
        }

        if (isDisplay == false)//当前参数不显示
            continue;

        // 实体的轮廓构件参数需要动态添加类型
        if (curParam->GetParameterDefinitionUid() == PARAMETER_UID(FormProfileFamilyBuiltInParameter) || curParam->GetParameterDefinitionUid() == PARAMETER_UID(FormProfileFamilyBuiltInParameter1))
        {
            ElementId instanceIdOfProfileFamily = ElementId::InvalidID;
            const IFamilyExtrusion * pFamilyExtrusion = FamilyElementUtils::CastElement<IFamilyExtrusion>(pEle);
            const IFamilySweep * pFamilySweep = FamilyElementUtils::CastElement<IFamilySweep>(pEle);
            const IFamilySweptLoft * pFamilySweptLoft = FamilyElementUtils::CastElement<IFamilySweptLoft>(pEle);
            if (pFamilyExtrusion)
            {
                instanceIdOfProfileFamily = pFamilyExtrusion->GetInstanceIdOfProfileFamily();
            }
            else if (pFamilySweep)
            {
                instanceIdOfProfileFamily = pFamilySweep->GetInstanceIdOfProfileFamily();
            }
            else if (pFamilySweptLoft)
            {
                if (curParam->GetParameterDefinitionUid() == PARAMETER_UID(FormProfileFamilyBuiltInParameter))
                {
                    instanceIdOfProfileFamily = pFamilySweptLoft->GetInstanceIdOfProfileFamily1();
                }
                else if(curParam->GetParameterDefinitionUid() == PARAMETER_UID(FormProfileFamilyBuiltInParameter1))
                {
                    instanceIdOfProfileFamily = pFamilySweptLoft->GetInstanceIdOfProfileFamily2();
                }
            }

            IElement * pInstanceElement = pDoc->GetElement(instanceIdOfProfileFamily);
            if (pInstanceElement)
            {
                IInstance * pInstance = quick_cast<IInstance>(pInstanceElement);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance != nullptr, L"pInstance为空！", L"paramodel", L"2024-02-20");
                DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance->GetBasicInformation() != nullptr, L"pInstance->GetBasicInformation()为空！", L"paramodel", L"2024-02-20");

                IType* pCurElementType = pInstance->GetBasicInformation()->GetType();
                if (pCurElementType)
                {
                    std::vector<OwnerPtr<IParameterValueDisplayString>> opDisplayStrings;
                    gcmp::IInstanceType* pCurrentInstanceType = gcmp::quick_cast<gcmp::IInstanceType>(pCurElementType);
                    if (pCurrentInstanceType)
                    {
                        gcmp::IFamily* pCurrentFamily = pCurrentInstanceType->GetFamily();
                        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentFamily != nullptr, L"pCurrentFamily为空！", L"paramodel", L"2024-02-20");

                        const IElementBasicInformation* pFamilyBasicInformation = pCurrentFamily->GetBasicInformation();
                        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyBasicInformation != nullptr, L"pFamilyBasicInformation为空！", L"paramodel", L"2024-02-20");

                        std::vector<IInstanceType*> instanceTypes = pCurrentFamily->GetInstanceTypes();
                        FOR_EACH(instanceType, instanceTypes)
                        {
                            DBG_WARN_AND_CONTINUE_UNLESS(instanceType != nullptr, L"instanceType为空！", L"paramodel", L"2024-02-20");

                            const IElementBasicInformation* pInstanceTypeBasicInformation = instanceType->GetBasicInformation();
                            DBG_WARN_AND_CONTINUE_UNLESS(pInstanceTypeBasicInformation != nullptr, L"pInstanceTypeBasicInformation为空！", L"paramodel", L"2024-02-20");

                            OwnerPtr<IParameterValueStorage> opParamValueStorage = IParameterValueElementId::Create(pInstanceTypeBasicInformation->GetElementId());
                            DBG_WARN_AND_CONTINUE_UNLESS(opParamValueStorage != nullptr, L"opParamValueStorage为空！", L"paramodel", L"2024-02-20");
                            opDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opParamValueStorage), pFamilyBasicInformation->GetName() + L":" + pInstanceTypeBasicInformation->GetName()));
                        }

                        OwnerPtr<IParameterValueList> opValueList = IParameterValueList::CreateParameterStaticValueList(curParam->GetParameterDefinitionUid(), opDisplayStrings);
                        DBG_WARN_AND_RETURN_VOID_UNLESS(opValueList != nullptr, L"opValueList为空！", L"paramodel", L"2024-02-20");
                        OwnerPtr<IParameterDisplay> opParameterDisplay = IParameterDisplay::CreateParameterDisplayDropdownList(curParam->GetParameterDefinitionUid(), TransferOwnership(opValueList));
                        DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterDisplay != nullptr, L"opParameterDisplay为空！", L"paramodel", L"2024-02-20");
                        if (!IParameterDisplayManager::AddBuiltInParameterDisplay(TransferOwnership(opParameterDisplay)))
                        {
                            opValueList = IParameterValueList::CreateParameterStaticValueList(curParam->GetParameterDefinitionUid(), opDisplayStrings);
                            DBG_WARN_AND_RETURN_VOID_UNLESS(opValueList != nullptr, L"opValueList为空！", L"paramodel", L"2024-02-20");
                            opParameterDisplay = IParameterDisplay::CreateParameterDisplayDropdownList(curParam->GetParameterDefinitionUid(), TransferOwnership(opValueList));
                            DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterDisplay != nullptr, L"opParameterDisplay为空！", L"paramodel", L"2024-02-20");
                            IParameterDisplayManager::ReplaceBuiltInParameterDisplay(TransferOwnership(opParameterDisplay));
                        }
                    }
                }
            }
        }
        params.push_back(TransferOwnership(curParam));
        paramMultiVals.push_back(isMultiValue);
    }
}

gfam::GnufPropertyPallet::GnufPropertyPallet()
    : gnuf::ArrangementAreaContent(s_key)
    , m_uiDocumentEventHandler(nullptr)
    , m_uiViewEventHandler(nullptr)
    , m_selectionChangeEventHandler(nullptr)
    , m_curUiDocId(-1)
    , m_defaultElementId(ElementId::InvalidID)
    , m_tmpPreSetElementId(ElementId::InvalidID)
    , m_endOfTransactionProcessorId(-1)
{
}

gfam::GnufPropertyPallet::~GnufPropertyPallet()
{
}

gfam::InstanceNameValuePairsComponent * gfam::GnufPropertyPallet::GetInstanceNameValuePairsBuilder()
{
    return s_instanceNameValuePairsBuilder.get();
}

gfam::FamilyTypeIntegratedComponent * gfam::GnufPropertyPallet::GetFamilyTypeComponentBuilder()
{
    return s_familyTypeComponentBuilder.get();
}

gfam::GnufPropertyPallet * gfam::GnufPropertyPallet::Get()
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(gnuf::ArrangementAreaContentManager::get() != nullptr, L"gnuf::ArrangementAreaContentManager::get()为空！", L"paramodel", L"2024-02-20");
    return static_cast<GnufPropertyPallet*>(gnuf::ArrangementAreaContentManager::get()->contentBy(s_key));
}

void gfam::GnufPropertyPallet::Initialize()
{
    static GnufPropertyPallet s_gnufPropertyPallet;
}

void gfam::GnufPropertyPallet::InitContent()
{
    m_uiDocumentEventHandler = NEW_AS_OWNER_PTR(PropertyPalletUiDocEventHandler);
    m_uiViewEventHandler = NEW_AS_OWNER_PTR(PropertyPalletUiViewEventHandler);
    m_selectionChangeEventHandler = NEW_AS_OWNER_PTR(PropertyPalletSelectionChangeEventHandler);

    m_elementChangeObserver = NEW_AS_OWNER_PTR(SelElementChangeObserver, this);
    m_inputEvent = NEW_AS_OWNER_PTR(GnufPropertyPanelEvent, L"PropertyPanelEvent", this);
    m_inputFinishedEvent = NEW_AS_OWNER_PTR(GnufPropertyPanelEvent, L"PropertyPanelEditFinishedEvent", this);

    if (m_inputEvent)
    {
        //m_inputEvent->Add()
    }

    DBG_WARN_AND_RETURN_VOID_UNLESS(ISelection::Get() != nullptr, L"ISelection::Get()为空！", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(ISelection::Get()->GetSelectionChangeEvent() != nullptr, L"GetSelectionChangeEvent()为空！", L"paramodel", L"2024-02-20");
    ISelection::Get()->GetSelectionChangeEvent()->Add(m_selectionChangeEventHandler.get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(GetUiDocumentEvent() != nullptr, L"GetUiDocumentEvent()为空！", L"paramodel", L"2024-02-20");
    GetUiDocumentEvent()->Add(m_uiDocumentEventHandler.get());;
    DBG_WARN_AND_RETURN_VOID_UNLESS(GetUiViewEvent() != nullptr, L"GetUiViewEvent()为空！", L"paramodel", L"2024-02-20");
    GetUiViewEvent()->Add(m_uiViewEventHandler.get());
}

void gfam::GnufPropertyPallet::Refresh()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(s_familyTypeComponentBuilder != nullptr, L"s_familyTypeComponentBuilder为空！", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(s_instanceNameValuePairsBuilder != nullptr, L"s_instanceNameValuePairsBuilder为空！", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_qtGnufPropertyPallet != nullptr, L"m_qtGnufPropertyPallet为空！", L"paramodel", L"2024-02-20");
    
    if (IsVisible() && IsEnable())
    {
        {
            std::vector<gcmp::ElementId> selElements = GetSelectedElements();
            if (selElements.empty())
            {
                GetShowElements(selElements);
            }
            if (selElements.empty())
                return;

            s_familyTypeComponentBuilder->SetDocument(GetDocument());
            s_familyTypeComponentBuilder->SetFamilyTypes(m_qtGnufPropertyPallet->familyTypes());
            s_familyTypeComponentBuilder->SetElementIds(selElements);
            s_familyTypeComponentBuilder->SetStatusOfAddAndModifyButton();
            s_familyTypeComponentBuilder->BuildFamilyTypeComponent();
        }
        
        {
            std::vector<ElementId> selElements;
            GetShowElements(selElements);
            if (selElements.empty())
                return;

            s_instanceNameValuePairsBuilder->SetDocument(GetDocument());
            s_instanceNameValuePairsBuilder->SetNameValuePairs(m_qtGnufPropertyPallet->nameValuePairs());
            s_instanceNameValuePairsBuilder->SetElementIds(selElements);
            s_instanceNameValuePairsBuilder->BuildNameValuePairs();
        }
        s_instanceNameValuePairsBuilder->SetNeedUpdate(false);
    }
}

void gfam::GnufPropertyPallet::SetDefaultElementId(const gcmp::ElementId & idDefaultElement)
{
    m_defaultElementId = idDefaultElement;
    Refresh();
}

const gcmp::ElementId gfam::GnufPropertyPallet::GetDefaultElementId() const
{
    return m_defaultElementId;
}

void gfam::GnufPropertyPallet::SetPreSetElementId(const gcmp::ElementId & elementId)
{
    m_tmpPreSetElementId = elementId;
}

const gcmp::ElementId gfam::GnufPropertyPallet::GetPreSetElementId() const
{
    return m_tmpPreSetElementId;
}

gfam::IGnufPropertyPanelEvent * gfam::GnufPropertyPallet::GetInputEvent()
{
    return m_inputEvent.get();
}

void gfam::GnufPropertyPallet::SetEnabled(bool bEnable)
{
    if (m_qtGnufPropertyPallet != nullptr)
    {
        m_qtGnufPropertyPallet->setEnabled(bEnable);
    }
}

std::wstring gfam::GnufPropertyPallet::GetComponentTypeChangedEventId() const
{
    return L"PropertyPaletteComponentTypeChangedEvent";
}

std::wstring gfam::GnufPropertyPallet::GetComponentTypeModifiedPropertyEventId() const
{
    return L"PropertyPaletteComponentTypeModifiedPropertyEvent";
}

std::wstring gfam::GnufPropertyPallet::GetInstancePropertyItemChangedEventId() const
{
    return std::wstring();
}

bool gfam::GnufPropertyPallet::isVisible() const
{
    if (m_qtGnufPropertyPallet != nullptr)
    {
        return m_qtGnufPropertyPallet->isVisible();
    }
    return false;
}

void gfam::GnufPropertyPallet::setVisible(bool isVisible)
{
    if (m_qtGnufPropertyPallet != nullptr)
    {
        return m_qtGnufPropertyPallet->setVisible(isVisible);
    }
}

gfam::IGnufPropertyPanelEvent * gfam::GnufPropertyPallet::GetInputFinishedEvent()
{
    return m_inputFinishedEvent.get();
}

QWidget * gfam::GnufPropertyPallet::qtWidget()
{
    if (nullptr != m_pallet && nullptr != m_pallet->qtWidget()) 
    {
        return m_pallet->qtWidget();
    }

    return nullptr;
}

const QWidget * 
gfam::GnufPropertyPallet::qtWidget() const
{
    if (nullptr != m_pallet && nullptr != m_pallet->qtWidget())
    {
        return m_pallet->qtWidget();
    }

    return nullptr;
}

void gfam::GnufPropertyPallet::onPostGeometryChanged()
{
    gnuf::Utility::refreshQtWidgetGeometry(this);
}

void gfam::GnufPropertyPallet::onPostVisibilityChanged()
{
    if (nullptr != qtWidget() && nullptr != arrangementArea())
    {
        qtWidget()->setVisible(arrangementArea()->visible());
    }
}

gcmp::IDocument * gfam::GnufPropertyPallet::GetDocument() const
{
    if (gcmp::IUiDocumentViewManager::Get())
    {
        gcmp::IUiDocument* pUIDoc = gcmp::IUiDocumentViewManager::Get()->GetCurrentUiDocument();
        if (pUIDoc)
        {
            return pUIDoc->GetDbDocument();
        }
    }

    return nullptr;
}

void gfam::GnufPropertyPallet::CheckDocSwitched()
{
    gcmp::IDocument* pDoc = GetDocument();
    if (pDoc)
    {
        gcmp::RuntimeId uiDocId = pDoc->GetRuntimeId();
        if (m_defaultElementId.IsValid() && m_curUiDocId != uiDocId)
        {
            m_defaultElementId = ElementId::InvalidID;
        }
        m_curUiDocId = uiDocId;
    }
}

void gfam::GnufPropertyPallet::GetShowElements(std::vector<gcmp::ElementId>& selElements) const
{
    gcmp::IDocument* pDocument = GetDocument();
    if (!pDocument)
    {
        return;
    }

    selElements = GetSourceElements().empty() ? GetSelectedElements() : GetSourceElements();
    if (selElements.empty())
    {
        if (m_defaultElementId.IsValid())
        {
            selElements.push_back(m_defaultElementId);
        }
        else
        {
            if (gcmp::IUiDocumentViewManager::Get() == nullptr)
                return;

            gcmp::IUiView* pUIView = gcmp::IUiDocumentViewManager::Get()->GetCurrentUiView();
            if (pUIView == nullptr)
                return;

            gcmp::IModelView* pModelView = pUIView->GetModelView();
            if (pModelView == nullptr)
                return;

            if (pModelView->GetBasicInformation() == nullptr)
                return;

            selElements.push_back(pModelView->GetBasicInformation()->GetElementId());
        }
    }
}

bool gfam::GnufPropertyPallet::IsVisible() const
{
    const QWidget* parent = dynamic_cast<const QWidget*>(this->qtWidget());
    return parent != nullptr && parent->isVisible();
}

bool gfam::GnufPropertyPallet::IsEnable() const
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_qtGnufPropertyPallet, L"m_qtGnufPropertyPallet is nullptr!", L"paramodel", L"2024-02-20");
    return m_qtGnufPropertyPallet->isEnabled();
}

std::vector<gcmp::ElementId> gfam::GnufPropertyPallet::GetSelectedElements() const
{
    std::vector<ElementId> resultElements;

    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, resultElements, L"pDoc is nullptr!", L"paramodel", L"2024-02-20");

    if (!GetDocument())
        return resultElements;

    DBG_WARN_AND_RETURN_UNLESS(ISelection::Get(), resultElements, L"ISelection::Get() is nullptr!", L"paramodel", L"2024-02-20"); 
    const GraphicsNodeReferenceOwnerPtrSet& nodeRefs = ISelection::Get()->GetGraphicsNodeReferences();
    resultElements.reserve(nodeRefs.size());
    std::set<ElementId> nestedInstanceIds;
    FOR_EACH(selItem, nodeRefs)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(selItem, L"selItem is nullptr!", L"paramodel", L"2024-02-20");
        ElementId selectedId = selItem->GetElementId();

        resultElements.emplace_back(selectedId);
    }

    return resultElements;
}

std::vector<gcmp::ElementId> gfam::GnufPropertyPallet::GetSourceElements() const
{
    std::vector<gcmp::ElementId> sourceElements;
    //预设参数Element
    if (GetPreSetElementId().IsValid())
    {
        sourceElements.push_back(GetPreSetElementId());
    }
    return sourceElements;
}

bool gfam::GnufPropertyPallet::HasSelectedElements()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(ISelection::Get(), L"ISelection::Get() is nullptr!", L"paramodel", L"2024-02-20");
    return !ISelection::Get()->IsEmpty();
}

void gfam::GnufPropertyPallet::quitTransaction()
{
    if (s_instanceNameValuePairsBuilder)
    {
        s_instanceNameValuePairsBuilder->quitTransaction();
    }

    if (s_familyTypeComponentBuilder)
    {
        s_familyTypeComponentBuilder->quitTransaction();
    }
}

void gfam::GnufPropertyPallet::onPostConnectedWithArrangementArea()
{
    //connect到ArrangementAreaContent的时候才真正初始化内容
    InitContent();

    s_instanceNameValuePairsBuilder = NEW_AS_OWNER_PTR(InstanceNameValuePairsComponent);
    s_familyTypeComponentBuilder = NEW_AS_OWNER_PTR(FamilyTypeIntegratedComponent);
    m_qtGnufPropertyPallet = TransferOwnership(NEW_AS_OWNER_PTR(QtGnufPropertyPallet, this));

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pallet, L"m_pallet is nullptr!", L"paramodel", L"2024-02-20");
    m_pallet = NEW_AS_OWNER_PTR(gnuf::Pallet, arrangementArea());
    m_pallet->rHeader().caption = GBMP_TR(L"属性面板");
    m_pallet->rHeader().wantBackground = false;
    m_pallet->rHeader().canDragAndMove = false;
    m_pallet->setWantBorder(true);
    m_pallet->setQtContent(m_qtGnufPropertyPallet.get());
    m_pallet->show();

    gnuf::Utility::setQtWidgetParent(this);
}

void gfam::GnufPropertyPallet::onPreDisconnectedFromArrangementArea()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_qtGnufPropertyPallet.ReleaseOwnership(), L"m_qtGnufPropertyPallet.ReleaseOwnership() is nullptr!", L"paramodel", L"2024-02-20");
    m_qtGnufPropertyPallet.ReleaseOwnership()->destroy();

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pallet, L"m_pallet is nullptr!", L"paramodel", L"2024-02-20");
    m_pallet->hide(true);
    m_pallet.reset(nullptr);
}

void gfam::GnufPropertyPallet::onEvent(ArrangementAreaEvent* evt)
{
    switch (evt->type())
    {
    case ArrangementAreaEvent::EType::ePreferencesChanged:
        auto theEvt = static_cast<PreferencesChangedAreaEvent*>(evt);
        const Preferences* preferences = theEvt->preferences();
        DBG_WARN_AND_RETURN_VOID_UNLESS(preferences, L"preferences is nullptr", L"paramodel", L"2024-02-20");

        if (const auto* entry = preferences->changedEntryBy(PreferenceEntry::eTheme))
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_qtGnufPropertyPallet, L"m_qtGnufPropertyPallet is nullptr!", L"paramodel", L"2024-02-20");
            DBG_WARN_AND_RETURN_VOID_UNLESS(s_familyTypeComponentBuilder, L"s_familyTypeComponentBuilder is nullptr!", L"paramodel", L"2024-02-20");
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pallet, L"m_pallet is nullptr!", L"paramodel", L"2024-02-20");

            m_qtGnufPropertyPallet->refreshAppearance();
            s_familyTypeComponentBuilder->refreshAppearance();
            m_pallet->refresh();
        }
        break;
    }
}

void gfam::GnufPropertyPallet::AttachElementChangeObserver(gcmp::IUiView * pUIView)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIView != nullptr, L"pUIView不能为空", L"paramodel", L"2024-02-20");
    gcmp::IUiDocument* pUIDoc = pUIView->GetUiDocument();
    if (pUIDoc)
    {
        gcmp::IDocument* pDoc = pUIDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"doc不能为空", L"paramodel", L"2024-02-20");

        pDoc->AddElementsChangeEventHandler(gcmp::ElementsChangeEventType::ElementsPreUpdationEvent, m_elementChangeObserver.get());

        gcmp::OwnerPtr<gcmp::IEndOfTransactionProcessor> opEndOfTransactionProcessor = NEW_AS_OWNER_PTR(EndOfTransactionProcessorPropertyPallet, this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(opEndOfTransactionProcessor, L"opEndOfTransactionProcessor不能为空", L"paramodel", L"2024-02-20");
        m_endOfTransactionProcessorId = opEndOfTransactionProcessor->GetId();
        gcmp::UserTransactionUtils::AddEndOfProcessorAfterRegenerateAll(pDoc, TransferOwnership(opEndOfTransactionProcessor));
    }
}

gcmp::IUiDocumentEvent * gfam::GnufPropertyPallet::GetUiDocumentEvent() const
{
    IUiDocumentViewManager* pUiDocumentViewManager = IUiDocumentViewManager::Get();
    DBG_WARN_UNLESS(pUiDocumentViewManager, L"pUiDocumentViewManager为空", L"paramodel", L"2023-12-201");
    return pUiDocumentViewManager->GetUiDocumentEvent();
}

gcmp::IUiViewEvent * gfam::GnufPropertyPallet::GetUiViewEvent() const
{
    gcmp::IUiDocumentViewManager* pUiDocumentViewManager = gcmp::IUiDocumentViewManager::Get();
    DBG_WARN_UNLESS(pUiDocumentViewManager, L"pUiDocumentViewManager为空", L"paramodel", L"2024-02-20");
    return pUiDocumentViewManager->GetUiViewEvent();
}

gfam::InstanceNameValuePairsComponent::InstanceNameValuePairsComponent()
    : m_connected(true)
    , m_isNeedUpdate(false)
    , m_isPropertyValueChanged(false)
    , m_canPropertyTableBeUpdated(false)
    , m_bTransactionIsCommitting(false)
{
}

bool gfam::InstanceNameValuePairsComponent::UpdatePropertyItemToElement(gnuf::Item * pItem)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(!m_elementIds.empty(), L"m_elementIds为空", L"paramodel", L"2024-02-20");
    IElement* pElement = m_wpDoc->GetElement(m_elementIds[0]);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement != nullptr, L"pElement为空", L"paramodel", L"2024-02-20");

    int iParamDefId = pItem->userData().cast<ItemInfo>().ParamId;
    OwnerPtr<IParameter> param;
    if (pElement->GetElementParameters())
    {
        param = pElement->GetElementParameters()->GetParameterById(iParamDefId);
    }
    DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param为空？", L"paramodel", L"2024-02-20");

    GnufElementPropertyPalletMaterialSelectionDialogEvents materialSelectionDialogEvents(m_wpDoc.Get(), iParamDefId);
    GraphicsMaterialLibraryDialogEventsScope materialSelectionDialogEventsScope(&materialSelectionDialogEvents);

    if (!CheckParameterValid(m_wpDoc.Get(), pItem, param.get(), pElement, m_elementIds))
        return false;

    //如果不显示此param，则略过
#pragma warning(push)
#pragma warning(disable: 4996)
    if (param->GetParameterDefinition() && param->GetParameterDefinition()->GetDisplayType() == ParameterDisplayType::NoDisplay)
        return false;
#pragma warning(pop)

    if (m_tmpPreSetElementId.IsValid())
    {
        const IElementParameters* pElementParameters = pElement->GetElementParameters();
        if (pElementParameters && !pElementParameters->IsPresetParameter(param->GetParameterDefinitionUid()))
            return false;
    }

    if (m_upUserTransaction == nullptr)
    {
        m_upUserTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改构件属性"), true);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_upUserTransaction, L"m_upUserTransaction为空", L"paramodel", L"2024-02-20");
    }
    if (!m_upUserTransaction->IsStarted())
    {
        m_upUserTransaction->Start();
    }

    bool bCommitAlways = false;
    OwnerPtr<IParameterValueStorage> opCurrentParamValue = nullptr;
    if (!GetCurrentParamValue(m_wpDoc.Get(), param.get(), pItem, m_elementIds, opCurrentParamValue, bCommitAlways))
    {
        if (m_upUserTransaction && m_upUserTransaction->IsStarted())
        {
            m_upUserTransaction->Rollback();
        }
        return false;
    }

    bool isParameterChanged = false;
    std::vector<ElementId> elementIdsToUpdateStyle;
    FOR_EACH(sleEle, m_elementIds)
    {
        IElement* pElement = m_wpDoc->GetElement(sleEle);
        DBG_WARN_AND_RETURN_UNLESS(pElement != nullptr, false, L"pElement为空", L"paramodel", L"2024-02-20");

        if (pElement->GetElementParameters())
            param = pElement->GetElementParameters()->GetParameterById(iParamDefId);

        bool isUpdateItem = false;
        if (!m_upUserTransaction->IsStarted())
        {
            m_upUserTransaction->Start();
        }
        bool bSuccess = SaveParamValueToElement(m_wpDoc.Get(), pElement, param.get(), opCurrentParamValue->Clone(), isUpdateItem);
        if (!bSuccess)
        {
            if (m_upUserTransaction && m_upUserTransaction->IsStarted())
            {
                m_upUserTransaction->Rollback();
                isParameterChanged = false;
            }
            break;
        }
        if (isUpdateItem)
        {
            isParameterChanged = true;
            if (param->GetName() == L"结构类型")
            {
                elementIdsToUpdateStyle.push_back(pElement->GetElementId());
            }

            // 切换显示模式后，要强制更新，工作平面样式才会更新
            if (param->GetName() == L"显示模式")
            {
                std::vector<IElement*> pWorkPlanes = m_wpDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_WORK_PLANE);
                FOR_EACH(pWorkPlane, pWorkPlanes)
                {
                    elementIdsToUpdateStyle.push_back(pWorkPlane->GetElementId());
                }
            }
        }
        UpdatePresetParamValue(isParameterChanged, pElement, param.get());
    }

    //切换结构类型改变二次类别后，要强制更新这些实例，样式才会更新
    if (!elementIdsToUpdateStyle.empty() && m_wpDoc->GetRegenerator())
    {
        m_wpDoc->GetRegenerator()->ForceRegeneratingElements(elementIdsToUpdateStyle);
    }

    if (isParameterChanged)
    {
        PropertyPanelEventArgs args(STR_FAM_EVENT_TYPE_CHANGE_PROPERTY_PANEL_PARAMETER, StringUtil::ToWString(pElement->GetElementId().AsInt64()));
        args.SetPropertyItemUniqueId(StringUtil::ToWString(iParamDefId));
        GnufPropertyPallet* propertyPalette = GnufPropertyPallet::Get();
        if (propertyPalette && propertyPalette->GetInputEvent())
        {
            GnufPropertyPanelEvent* pGnufPropertyPanelEvent = dynamic_cast<GnufPropertyPanelEvent*>(propertyPalette->GetInputEvent());
            if (pGnufPropertyPanelEvent)
            {
                pGnufPropertyPanelEvent->Emit(&args);
            }
        }
    }

    if (bCommitAlways && isParameterChanged)//添加了isParameterChanged判断，当属性值修改不成功时 m_upUserTransaction->Rollback()，不应该再执行  m_upUserTransaction->Commit()
    {
        m_bTransactionIsCommitting = true;
        m_upUserTransaction->Commit();
        m_bTransactionIsCommitting = false;

        isParameterChanged = false;
    }
    if (isParameterChanged)
    {
        NotifyFinishEvent(STR_FAM_EVENT_TYPE_CHANGE_PROPERTY_PANEL_PARAMETER, StringUtil::ToWString(pElement->GetElementId().AsInt64()));
    }
    else
    {
        if (m_upUserTransaction && m_upUserTransaction->IsStarted())
        {
            m_upUserTransaction->Rollback();
        }
    }

    //更新可视化场景
    UpdateViewVisual();

    bool refresh = false;
    //属性表中Check或List的值改变后,属性组或属性条目可能变化,希望刷新属性表
    if (pItem->cast<gnuf::Check>() || pItem->cast<gnuf::List>())
        refresh = true;
    //更新属性表
    BuildNameValuePairs(refresh);

    return isParameterChanged;
}

bool gfam::InstanceNameValuePairsComponent::UpdatePropertyTableToElement()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空!", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_pNameValuePairs, L"m_pNameValuePairs为空!", L"paramodel", L"2024-02-20");
    m_connected = false;
    bool isSolveSuccess = true;
    bool error = false;
    std::set<const gfam::IFamilyConstraint*> failedFeatureGroup;
    FOR_EACH(selEle, m_elementIds)
    {
        IElement* pElement = m_wpDoc->GetElement(selEle);
        if (!pElement)
            continue;

        gnuf::NameValuePairs::RawContents blocks = m_pNameValuePairs->rawContents();
        FOR_EACH(block, blocks)
        {
            if (!block)
            {
                continue;
            }

            if (gnuf::NameValuePairBlock* nvpb = block->cast<gnuf::NameValuePairBlock>())
            {
                gnuf::NameValuePairBlock::RawContents blockContents = nvpb->rawContents();
                FOR_EACH(content, blockContents)
                {
                    gnuf::NameValuePair* nvp = content->cast<gnuf::NameValuePair>();
                    DBG_WARN_AND_CONTINUE_UNLESS(nullptr != nvp, L"A name-value not existed!", L"paramodel", L"2024-02-20");
                    if (gnuf::Item* pItem = nvp->value())
                    {
                        gnuf::Item* noBlockItem = nullptr;
                        if (pItem->type() == gnuf::EItemType::eBlock)
                        {
                            if (nullptr == pItem->cast<gnuf::Block>())
                            {
                                continue;
                            }

                            if (!pItem->cast<gnuf::Block>()->rawContents().empty())
                            {
                                noBlockItem = pItem->cast<gnuf::Block>()->rawContents()[0];
                            }
                        }
                        else
                        {
                            noBlockItem = pItem;
                        }

                        bool bCommitAlways = false;
                        UpdatePropertyItemToElementParameter(noBlockItem, pElement, m_elementIds, bCommitAlways, error);

                        if (error)
                        {
                            if (m_upUserTransaction && m_upUserTransaction->IsStarted())
                            {
                                m_upUserTransaction->Rollback();
                            }
                            break;
                        }
                    }
                }
            }
        }

#pragma region 以下代码针对族文档进行处理，如需复用请酌情删除，同时删除相关头文件
        //中间的参数修改过程中可以不解算文档，在属性面板的参数都更新后再解算
        //重新获取一下pElement,因为上面代码可能会事务回滚，造成当前选定的element不可用，pElement为野指针。
        pElement = m_wpDoc->GetElement(selEle);
        //如果pElement为空跳出当前element继续下一个
        if (nullptr== pElement)
        {
            continue;
        }
        if (m_wpDoc->IsFamilyDocument())
        {
            IFamilyRapidForm *pRapidForm = FamilyElementUtils::CastElement<IFamilyRapidForm>(pElement);
            if (pRapidForm)
            {
                IElementParameters* pRapidFormParameters = pElement->GetElementParameters();
                if (pRapidFormParameters)
                {
                    std::vector<OwnerPtr<IParameter>> parameters = pRapidFormParameters->GetAllParameters();
                    IParameter *paramter1 = nullptr;
                    IParameter *paramter2 = nullptr;
                    FOR_EACH(parameter, parameters)
                    {
                        DBG_WARN_AND_CONTINUE_UNLESS(parameter, L"parameter为空！", L"paramodel", L"2024-02-20");
                        if (parameter->GetName()==L"外径")
                        {
                            paramter1 = parameter.get();
                        }
                        else if (parameter->GetName() == L"内径")
                        {
                            paramter2 = parameter.get();
                        }
                    }
                    if (paramter1&&paramter2)
                    {
                        if (paramter1->GetValueAsDouble() < paramter2->GetValueAsDouble())
                        {
                            UiCommonDialog::ShowMessageBox(GBMP_TR(L"String_Geometry_Constraint"),
                                L"修改失败，内径应小于外径！", (int)UiCommonDialog::ButtonType::OK);
                            isSolveSuccess = false;
                            break;
                        }
                    }
                }
            }
            FamilySolverResult result = gfam::FamilySolverUtils::SolveDocument(m_wpDoc.Get(), &failedFeatureGroup);
            if (result != FamilySolverResult::Ok)
            {
                UiCommonDialog::ShowMessageBox(GBMP_TR(L"String_Geometry_Constraint"),
                    gfam::FamilySolverUtils::GetSolverResultString(result), (int)UiCommonDialog::ButtonType::OK);

                if (IsA<gfam::IFamilyGeometryConstraint>(pElement))
                {
                    continue;
                }

                isSolveSuccess = false;
                break;
            }
        }
#pragma endregion

        pElement->FinishEditing();
    }

    if (m_upUserTransaction && m_upUserTransaction->IsStarted())
    {
        if (isSolveSuccess)
        {
            //标记不需要更新整个属性表，避免提交事务导致更新
            m_bTransactionIsCommitting = true;
            m_upUserTransaction->Commit();
            m_bTransactionIsCommitting = false;
            m_isNeedUpdate = false;
        }
        else
        {
            m_upUserTransaction->Rollback();

            {
                m_upUserTransaction->Start();
                FamilyHighlightUtils::HighlightConstraints(m_wpDoc.Get(), failedFeatureGroup, nullptr);
                m_upUserTransaction->Commit();
            }
        }
    }

    //更新可视化场景
    UpdateViewVisual();
    m_connected = true;
    //更新属性表
    BuildNameValuePairs(false);
    return true;
}

void gfam::InstanceNameValuePairsComponent::quitTransaction()
{
    if (m_upUserTransaction)
    {
        m_upUserTransaction = nullptr;
    }
}

bool gfam::InstanceNameValuePairsComponent::CheckRadialArrayParameter(int paramDefId, int newParamDefId, std::wstring * errorMessage)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    IFamilyManager* pFamilyManager = IFamilyManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空", L"paramodel", L"2024-02-20");

    gcmp::IParameterDefinitionLibrary* paramDefinitionLibrary = gcmp::IParameterDefinitionLibrary::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(paramDefinitionLibrary, L"paramDefinitionLibrary为空", L"paramodel", L"2024-02-20");

    if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(RadialArrayCountBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            if (pParameter->GetValueAsInt() < 2)
            {
                *errorMessage = L"环形阵列个数至少为2！";
                return false;
            }

            if (pParameter->GetValueAsInt() > 999)
            {
                *errorMessage = L"环形阵列个数最多为999！";
                return false;
            }
        }
    }
    else if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(RadialArrayAngleBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            double dValue = pParameter->GetValueAsDouble();
            int pRadialArrayCountParameterDefinitionId = paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(RadialArrayCountBuiltInParameter));
            const IParameter* pRadialArrayCountParameter = pFamilyManager->GetParameter(pRadialArrayCountParameterDefinitionId);
            if (pRadialArrayCountParameter)
            {
                dValue = dValue * (pRadialArrayCountParameter->GetValueAsInt() - 1);
                if (dValue <= 0.0)
                {
                    *errorMessage = L"环阵整体角度应大于0度！";
                    return false;
                }

                if (dValue >= Constants::MATH_2PI)
                {
                    *errorMessage = L"环阵整体角度应小于360度！";
                    return false;
                }
            }
        }
    }
    else if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(RadialArrayTotalAngleBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            double dValue = pParameter->GetValueAsDouble();
            if (dValue <= 0.0)
            {
                *errorMessage = L"环阵整体角度应大于0度！";
                return false;
            }

            if (dValue > Constants::MATH_2PI&&fabs(dValue - Constants::MATH_2PI)>Constants::DOUBLE_EPS)
            {
                *errorMessage = L"环阵整体角度不能超过360度！";
                return false;
            }
        }
    }
    else if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(RadialArrayRadiusBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            if (pParameter->GetValueAsDouble() <= 0.0)
            {
                *errorMessage = L"环阵半径应大于0！";
                return false;
            }
        }
    }

    return true;
}

bool gfam::InstanceNameValuePairsComponent::CheckLinearArrayParameter(int paramDefId, int newParamDefId, std::wstring * errorMessage)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    IFamilyManager* pFamilyManager = IFamilyManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空", L"paramodel", L"2024-02-20");

    gcmp::IParameterDefinitionLibrary* paramDefinitionLibrary = gcmp::IParameterDefinitionLibrary::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(paramDefinitionLibrary, L"paramDefinitionLibrary为空", L"paramodel", L"2024-02-20");

    if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(LinearArrayCountBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            if (pParameter->GetValueAsInt() < 1)
            {
                *errorMessage = L"线形阵列个数至少为1！";
                return false;
            }

            if (pParameter->GetValueAsInt() > 999)
            {
                *errorMessage = L"阵列个数最多为999！";
                return false;
            }
        }
    }
    else if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(LinearArrayDistanceBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            double distance = pParameter->GetValueAsDouble();
            if (distance <= 0.0)
            {
                *errorMessage = L"阵列间距应大于0！";
                return false;
            }
        }
    }
    else if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(LinearArrayTotalDistanceBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            double distance = pParameter->GetValueAsDouble();
            if (distance <= 0.0)
            {
                *errorMessage = L"阵列总距应大于0！";
                return false;
            }
        }
    }

    return true;
}

bool gfam::InstanceNameValuePairsComponent::CheckRichTextParameter(int paramDefId, int newParamDefId, std::wstring * errorMessage)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    IFamilyManager* pFamilyManager = IFamilyManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyManager, L"pFamilyManager为空", L"paramodel", L"2024-02-20");

    gcmp::IParameterDefinitionLibrary* paramDefinitionLibrary = gcmp::IParameterDefinitionLibrary::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(paramDefinitionLibrary, L"paramDefinitionLibrary为空", L"paramodel", L"2024-02-20");

    if (paramDefId == paramDefinitionLibrary->GetParameterDefinitionIdByUid(PARAMETER_UID(TextNameBuiltInParameter)))
    {
        const IParameter* pParameter = pFamilyManager->GetParameter(newParamDefId);
        if (pParameter)
        {
            if (pParameter->GetValueAsString().empty())
            {
                *errorMessage = L"文字内容不能为空！";
                return false;
            }
        }
    }

    return true;
}

bool gfam::InstanceNameValuePairsComponent::UpdatePropertyItemToElementParameter(const gnuf::Item * pItem, gcmp::IElement * pElement, const std::vector<gcmp::ElementId>& selElements, bool & bCommitNow, bool & error)
{
    error = false; //更新错误标记
    if (pItem == nullptr || pElement == nullptr)
    {
        return false;
    }

    OwnerPtr<IParameter> opParam;
    if (pElement->GetElementParameters())
    {
        IElementParameters* pElementParameters = pElement->GetElementParameters();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pElementParameters, L"pElementParameters为空!", L"paramodel", L"2024-02-20");
        opParam = pElementParameters->GetParameterById(pItem->userData().cast<ItemInfo>().ParamId);
    }

    if (!CheckParameterValid(m_wpDoc.Get(), pItem, opParam.get(), pElement, selElements))
    {
        return false;
    }

    DBG_WARN_AND_RETURN_FALSE_UNLESS(opParam, L"opParam为空!", L"paramodel", L"2024-02-20");

    //如果不显示此param，则略过
    const IParameterDefinition*  pParameterDefinition = opParam->GetParameterDefinition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pParameterDefinition, L"pParameterDefinition为空!", L"paramodel", L"2024-02-20");
#pragma warning(push)
#pragma warning(disable: 4996)
    if (pParameterDefinition->GetDisplayType() == ParameterDisplayType::NoDisplay)
        return false;
#pragma warning(pop)

    if (m_tmpPreSetElementId.IsValid())
    {
        const IElementParameters* pElementParameters = pElement->GetElementParameters();
        if (pElementParameters &&
            !pElementParameters->IsPresetParameter(opParam->GetParameterDefinitionUid()))
        {
            return false;
        }
    }

    if (m_upUserTransaction == nullptr)
    {
        m_upUserTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改构件属性"), true);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(m_upUserTransaction, L"m_upUserTransaction is nullptr", L"paramodel", L"2024-02-20");
    }
    if (!m_upUserTransaction->IsStarted())
    {
        m_upUserTransaction->Start();
    }

    bool bParameterChanged = false;
    OwnerPtr<IParameterValueStorage> opCurrentParamValue = nullptr;
    if (!GetCurrentParamValue(m_wpDoc.Get(), opParam.get(), pItem, selElements, opCurrentParamValue, bCommitNow))
    {
        return false;
    }

    if (!SaveParamValueToElement(m_wpDoc.Get(), pElement, opParam.get(), opCurrentParamValue, bParameterChanged))
    {
        error = true;
        return false;
    }
    UpdatePresetParamValue(bParameterChanged, pElement, opParam.get());

    return bParameterChanged;
}

void gfam::InstanceNameValuePairsComponent::UpdateViewVisual() const
{
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");

    IUiDocument* pUIDoc = pUiDocViewMgr->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc != nullptr, L"pUIDoc为空", L"paramodel", L"2024-02-20");
    pUIDoc->UpdateViewByVisibilityConditionChanged();
    pUIDoc->UpdateView();
}

void gfam::InstanceNameValuePairsComponent::CheckLeaveEventHandler()
{
    //在脚本回放过程中，忽略这个逻辑处理。
    //在脚本回放过程中,光标位置是缺省的,导致光标位置超出属性面板范围。
    //程序会错误认为光标已经移除属性面板。
    if (gcmp::JournalUtils::IsInReplay() == false)
    {
        if (qtGnufPropertyPallet() && qtGnufPropertyPallet()->isMouseLeavePropertyPallet())
        {
            onApply();
        }
    }
}

void gfam::InstanceNameValuePairsComponent::UpdatePresetParamValue(bool bParameterChanged, gcmp::IElement * pElement, gcmp::IParameter * param) const
{
    // update 预设参数中的值
    if (bParameterChanged && m_tmpPreSetElementId.IsValid())
    {
        IPresetParameterManager* pPreSetMgr = IPresetParameterManager::Get(m_wpDoc.Get());
        DBG_WARN_AND_RETURN_VOID_UNLESS(pPreSetMgr, L"pPreSetMgr为空", L"paramodel", L"2024-02-20");

        Int32 categorySecondkey = pPreSetMgr->GetPresetValuesGroupId(pElement);
        IElementParameters* pParameters = pElement->GetElementParameters();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pParameters, L"pParameters为空", L"paramodel", L"2024-02-20");

        const IElementParameters* pElementParameters = pElement->GetElementParameters();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pElementParameters, L"pElementParameters为空", L"paramodel", L"2024-02-20");

        std::vector<OwnerPtr<IParameter>> allParameters = pParameters->GetAllParameters();
        FOR_EACH(parameter, allParameters)
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(parameter, L"parameter为空", L"paramodel", L"2024-02-20");

            if (pElementParameters->IsPresetParameter(parameter->GetParameterDefinitionUid()))
            {
                DBG_WARN_AND_CONTINUE_UNLESS(pElement->GetBasicInformation(), L"pElement->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
                if (pPreSetMgr->SetPresetParameter(pElement->GetBasicInformation()->GetCategoryUid(), categorySecondkey, parameter.get()))
                    bParameterChanged = true;
            }
        }
    }
}

bool gfam::InstanceNameValuePairsComponent::RefreshByParameterValueStorage(gcmp::IParameterValueStorage * pCurrentParamValue, int parameterDefinitionId)
{
    if (m_upUserTransaction == nullptr || !m_upUserTransaction->IsStarted())
    {
        DBG_WARN(L"事务未启动", L"paramodel", L"2024-02-20");
        return false;
    }

    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空!", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(!m_elementIds.empty(), L"m_elementIds为空!", L"paramodel", L"2024-02-20");

    //IHighlights::Get()->Clear();

    OwnerPtr<IParameter> param;
    bool isRollback = false;
    FOR_EACH(sleEle, m_elementIds)
    {
        IElement* pElement = m_wpDoc->GetElement(sleEle);
        DBG_WARN_AND_RETURN_UNLESS(pElement != nullptr, false, L"pElement为空", L"paramodel", L"2024-02-20");
        bool isUpdateItem = false;
        if (pElement->GetElementParameters())
            param = pElement->GetElementParameters()->GetParameterById(parameterDefinitionId);
        bool ok = SaveParamValueToElement(m_wpDoc.Get(), pElement, param.get(), pCurrentParamValue->Clone(), isUpdateItem);
        if (!ok)
        {
            isRollback = true;
            break;
        }

        UpdatePresetParamValue(isUpdateItem, pElement, param.get());
    }

    if (isRollback)
    {
        m_upUserTransaction->Rollback();
    }
    else
    {
        m_upUserTransaction->Commit();
    }

    //更新可视化场景
    UpdateViewVisual();
    //更新属性表
    s_familyTypeComponentBuilder->BuildFamilyTypeComponent();
    BuildNameValuePairs(true);

    m_upUserTransaction->Start();

    return true;
}

void gfam::InstanceNameValuePairsComponent::onApply()
{
    QtGnufPropertyPallet* pQtBnufPropertyPallet = qtGnufPropertyPallet();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQtBnufPropertyPallet, L"pQtBnufPropertyPallet为空？", L"paramodel", L"2024-02-20");

    if (!pQtBnufPropertyPallet->isPropertyValueChanged())
    {
        if (!m_bTransactionIsCommitting && m_upUserTransaction != nullptr && m_upUserTransaction->IsStarted())
        {
            m_upUserTransaction->Rollback();
        }
        return;
    }
    pQtBnufPropertyPallet->onApplyStatus();
    UpdatePropertyTableToElement();
}

void gfam::InstanceNameValuePairsComponent::onPropertyValueChanged(gnuf::Item * pItem)
{
    if (!UpdateItemMultiValue(pItem, false))
        return;

    // 基类修改属性项事件处理
    if (UpdatePropertyItemToElement(pItem) && qtGnufPropertyPallet())
    {
        qtGnufPropertyPallet()->onPropertyValueChanged();

        //做光标离开检查事件处理
        CheckLeaveEventHandler();

        //发送属性参数变化事件，在CheckLeaveEventHandler后是为了确保修改属性面板的事务已经提交
        NotifyAfterParameterChanged(pItem);
    }
    else
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(GnufPropertyPallet::Get(), L"GnufPropertyPallet::Get()为空", L"paramodel", L"2024-02-20");
        GnufPropertyPallet::Get()->Refresh();
    }
}

void gfam::InstanceNameValuePairsComponent::OnPropertyBindButtonClicked(gnuf::Item * pItem)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pItem, L"pItem为空", L"paramodel", L"2024-02-20");
    int uniquiID = pItem->userData().cast<ItemInfo>().ParamId;

#pragma region 以下代码属于族和构建编辑器相关功能，如需复用请酌情删除，同时删除相关头文件
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_elementIds.empty(), L"m_elementIds为空", L"paramodel", L"2024-02-20");
    IElement* pElement = m_wpDoc->GetElement(m_elementIds[0]);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement != nullptr, L"pElement为空", L"paramodel", L"2024-02-20");

    gfam::IFamilyManager *pFamManager = gfam::IFamilyManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamManager != nullptr, L"pFamManager为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement != nullptr, L"pSelectedElement为空", L"paramodel", L"2024-02-20");
    OwnerPtr<IParameter> curParam;
    if (pElement->GetElementParameters())
        curParam = pElement->GetElementParameters()->GetParameterById(uniquiID);

    if (!CheckConstraintIsAllowedToModify(m_wpDoc.Get(), pElement, curParam.get()))
        return ;

    IElementParameters* param = pElement->GetElementParameters();
    if (!param)
    {
        return;
    }
    int curParamDefId = -1;
    IElementParameterBindings* paramBinding = param->GetElementParameterBindings();
    if (paramBinding)
    {
        curParamDefId = paramBinding->GetBindingSourceParameterDefinitionId(uniquiID);
    }

    onApply();

    WorkBench* pWorkBench = WorkBench::get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pWorkBench, L"pWorkBench为空!", L"paramodel", L"2024-02-20");
    QtWorkBenchWindow* pQtWorkBenchWindow = pWorkBench->qtWorkBenchWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQtWorkBenchWindow, L"pQtWorkBenchWindow为空!", L"paramodel", L"2024-02-20");
    GnufBindToFamilyParamDlg *pDialog = NEW_AS_QT(GnufBindToFamilyParamDlg, pQtWorkBenchWindow);
    pDialog->InitDialog(curParam.get(), curParamDefId, gfam::IFamilyManager::Get(m_wpDoc.Get()));
    if (pDialog->exec() != QDialog::Accepted)
    {
        return;
    }
    //由于GnufBindToFamilyParamDialog对话框，可能会有事务回退，会造成pFamManager 指针不稳定，所以重新获取一下
    pFamManager = gfam::IFamilyManager::Get(m_wpDoc.Get());
    Int32 newParamDefId = pDialog->GetBoundParamDefId();

    gcmp::IParameterDefinitionLibrary* paramDefinitionLibrary = gcmp::IParameterDefinitionLibrary::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(paramDefinitionLibrary, L"paramDefinitionLibrary为空", L"paramodel", L"2024-02-20");

    if (m_upUserTransaction == nullptr)
    {
        m_upUserTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改构件属性"), true);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_upUserTransaction != nullptr, L"m_upUserTransaction为空", L"paramodel", L"2024-02-20");
    }
    if (!m_upUserTransaction->IsStarted())
    {
        m_upUserTransaction->Start();
    }
    bool bRes = true;
    for (int i = 0; i < (int)m_elementIds.size(); ++i)
    {
        IElement* pSelectedElement = m_wpDoc->GetElement(m_elementIds[i]);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pSelectedElement != nullptr, L"pSelectedElement为空", L"paramodel", L"2024-02-20");

        IElementParameters* parameter = pSelectedElement->GetElementParameters();
        if (!parameter)
        {
            return;
        }
        OwnerPtr<IParameter> curParam;
        if (parameter)
            curParam = parameter->GetParameterById(uniquiID);
        DBG_WARN_AND_CONTINUE_UNLESS(nullptr != curParam, L"curParam为空", L"paramodel", L"2024-02-20");
        {
            std::wstring errorMessage;
            if (IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElement))
            {
                if (!CheckRichTextParameter(uniquiID, newParamDefId, &errorMessage))
                {
                    bRes = false;
                }

                if (!bRes)
                {
                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"参数绑定失败，") + errorMessage, (int)UiCommonDialog::ButtonType::OK);
                    m_upUserTransaction->Rollback();
                    UpdateViewVisual();
                    return;
                }
            }

            int oldParamDefId = -1;
            IElementParameterBindings* paramBindings = parameter->GetElementParameterBindings();
            DBG_WARN_AND_CONTINUE_UNLESS(nullptr != paramBindings, L"paramBindings为空", L"paramodel", L"2024-02-20");

            oldParamDefId = paramBindings->GetBindingSourceParameterDefinitionId(uniquiID);

            if (newParamDefId < 0)
            {
                if (oldParamDefId > 0)
                {
                    bRes = paramBindings->DeleteParameterBinding(uniquiID);
                }
            }
            else
            {
                if (oldParamDefId > 0)
                    bRes = paramBindings->ChangeParameterBinding(uniquiID, newParamDefId, pFamManager->GetElementId());
                else
                    bRes = paramBindings->AddParameterBinding(uniquiID, newParamDefId, pFamManager->GetElementId(), false);

                if (bRes && 
                    (nullptr != FamilyElementUtils::CastElement<const IFamilyForm>(pSelectedElement) 
                        || nullptr != FamilyElementUtils::CastElement<const IFamilyRapidShape>(pSelectedElement))
                    )
                {
                    std::set<const gfam::IFamilyConstraint*> failedFeatureGroup;
                    FamilySolverResult solveResult = FamilySolverUtils::SolveDocument(m_wpDoc.Get(), &failedFeatureGroup);

                    if (solveResult != FamilySolverResult::Ok)
                    {
                        errorMessage = FamilySolverUtils::GetSolverResultString(solveResult);
                        UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"参数绑定失败，") + errorMessage, (int)UiCommonDialog::ButtonType::OK);
                        m_upUserTransaction->Rollback();

                        {
                            m_upUserTransaction->Start();
                            FamilyHighlightUtils::HighlightConstraints(m_wpDoc.Get(), failedFeatureGroup, nullptr);
                            m_upUserTransaction->Commit();
                        }

                        UpdateViewVisual();
                        return;
                    }

                    IFamilyRapidForm *pRapidForm = FamilyElementUtils::CastElement<IFamilyRapidForm>(pSelectedElement);
                    if (pRapidForm)
                    {
                        IElementParameters* pRapidFormParameters = pElement->GetElementParameters();
                        if (pRapidFormParameters)
                        {
                            std::vector<OwnerPtr<IParameter>> parameters = pRapidFormParameters->GetAllParameters();
                            IParameter *paramter1 = nullptr;
                            IParameter *paramter2 = nullptr;
                            FOR_EACH(parameter, parameters)
                            {
                                DBG_WARN_AND_CONTINUE_UNLESS(parameter, L"parameter为空！", L"paramodel", L"2024-02-20");
                                if (parameter->GetName() == L"外径")
                                {
                                    paramter1 = parameter.get();
                                }
                                else if (parameter->GetName() == L"内径")
                                {
                                    paramter2 = parameter.get();
                                }
                            }
                            if (paramter1&&paramter2)
                            {
                                if (paramter1->GetValueAsDouble() < paramter2->GetValueAsDouble())
                                {
                                    UiCommonDialog::ShowMessageBox(GBMP_TR(L"String_Geometry_Constraint"),
                                        L"修改失败，内径应小于外径！", (int)UiCommonDialog::ButtonType::OK);
                                    m_upUserTransaction->Rollback();
                                    UpdateViewVisual();
                                    return;
                                }
                            }
                        }
                    }
                }
            }
            if (!bRes)
            {
                break;
            }
            const gfam::IFamilyParameterDefinition *pFamParamDef = pFamManager->GetFamilyParameterDefinition(newParamDefId);
            if (pFamParamDef != nullptr)
            {
                pFamManager->SetFamilyParameterAsDrive(pFamParamDef, curParam->IsDriveParameter());
                pFamManager->SetFamilyParameterAsGeometric(pFamParamDef, curParam->IsGeometricParameter());
            }
        }
    }
    if (bRes)
    {
        m_bTransactionIsCommitting = true;
        m_upUserTransaction->Commit();
        m_bTransactionIsCommitting = false;
        BuildNameValuePairs(false);
    }
    else
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"参数绑定失败"), (int)UiCommonDialog::ButtonType::OK);
        m_upUserTransaction->Rollback();
    }

    // 主动刷新视图
    UpdateViewVisual();
#pragma endregion
}

void gfam::InstanceNameValuePairsComponent::OnPropertyDropDownButtonClicked(gnuf::Item* pItem)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_elementIds.empty(), L"m_elementIds为空", L"paramodel", L"2024-02-20");
    IElement* pElement = m_wpDoc->GetElement(m_elementIds[0]);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"pElement为空", L"paramodel", L"2024-02-20");

    int iParamDefId = pItem->userData().cast<ItemInfo>().ParamId;
    OwnerPtr<IParameter> param;
    if (pElement->GetElementParameters())
        param = pElement->GetElementParameters()->GetParameterById(iParamDefId);

    auto* pParameterDefinition = param->GetParameterDefinition();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParameterDefinition, L"pParameterDefinition为空", L"paramodel", L"2024-02-20");
    gfam::IGnufParameterDisplayCustom* pDisplayCustom = gfam::GnufParameterDisplayCustomFactory::Get()->Find(pParameterDefinition->GetUid());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDisplayCustom, L"pDisplayCustom为空", L"paramodel", L"2024-02-20");

    if (LineStyleParameterDisplay* pLineStyleParameterDisplay = dynamic_cast<LineStyleParameterDisplay*>(pDisplayCustom))
    {
        auto info = pItem->info();
        DBG_WARN_AND_RETURN_VOID_UNLESS(info, L"info为空", L"paramodel", L"2024-02-20");

        if (info->caption() == LineStyleParameterDisplay::s_multiTypeText)
        {
            return;
        }

        // 必须添加相等条件判断，否则初始化阶段会报错
        if (ParameterStorageType::String == pParameterDefinition->GetStorageType()) // 线型
        {
            auto currentLineType = param->GetValueAsString();
            if (currentLineType.empty() || (currentLineType == info->caption()))
            {
                return;
            }
        }

        if (ParameterStorageType::Double == pParameterDefinition->GetStorageType()) // 线宽
        {
            double currentLineWidth = param->GetValueAsDouble();
            std::wstring numberString = gfam::GetFirstNumberString(info->caption());
            double newLineWidth = std::stof(numberString);
            if (abs(currentLineWidth - newLineWidth) < 0.0001)
            {
                return;
            }
        }
        pLineStyleParameterDisplay->onClicked(pItem);
    }

    onPropertyValueChanged(pItem);
}

void gfam::InstanceNameValuePairsComponent::onCurrentIndexChanged(gnuf::List * pList, int)
{
    onPropertyValueChanged(pList);
}

void gfam::InstanceNameValuePairsComponent::onTextChanged(gnuf::Text * pText)
{
    onPropertyValueChanged(pText);
}

void gfam::InstanceNameValuePairsComponent::onCheckStatusChanged(gnuf::Check * pCheck, bool)
{
    onPropertyValueChanged(pCheck);
}

void gfam::InstanceNameValuePairsComponent::onColorChanged(gnuf::ColorControl* pColorControl)
{
    onPropertyValueChanged(pColorControl);
}

void gfam::InstanceNameValuePairsComponent::onClicked(gnuf::Item * pItem)
{
    if (pItem->type() == gnuf::EItemType::ePushButton)
    {
        std::wstring strParamName;
        auto parent = pItem->parent();
        if (parent)
        {
            auto info = parent->info();
            if (info)
            {
                strParamName = info->caption();
            }
            if (parent && (parent->type() == EItemType::eDropdownBoard))
            {
                OnPropertyDropDownButtonClicked(pItem);
            }
            else if (parent&&strParamName == L"填充样式")
            {
                UpdatePropertyItemToElement(pItem);
                QtGnufPropertyPallet* pallet = qtGnufPropertyPallet();
                if (pallet)
                {
                    pallet->onPropertyValueChanged();
                }
                onApply();
            }
            else
            {
                OnPropertyBindButtonClicked(pItem);
            }
        }
    }
    else if (pItem->type() == gnuf::EItemType::eColorControl)
    {
        onApply();
    }
}

gfam::FamilyNameValuePairsComponent::FamilyNameValuePairsComponent(const std::wstring & title)
{
    m_familyNameComponent = NEW_AS_OWNER_PTR(FamilyTypeNameComponent, this, title, true);
    m_editFamilyType = NEW_AS_QT(QtEditFamilyType, this, title);
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_editFamilyType, L"m_editFamilyType为空", L"paramodel", L"2024-02-20");
    m_pNameValuePairs = m_editFamilyType->nameValuePairs();
}

bool gfam::FamilyNameValuePairsComponent::UpdatePropertyItemToElement(gnuf::Item * pItem)
{
    return false;
}

bool gfam::FamilyNameValuePairsComponent::UpdatePropertyTableToElement()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    IType* pickedType = quick_cast<IType>(m_wpDoc->GetElement(GetCurFamilyTypeId()));
    if (pickedType == nullptr)
        return false;

    IElementParameters* pParamBehavior = pickedType->GetElementParameters();
    if (!pParamBehavior)
        return false;

    // 更新"名称"参数
    FamilyTypeNameComponent* pFtnc = GetFamilyTypeNameComponent();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFtnc, L"pFtnc为空!", L"paramodel", L"2024-02-20");
    QtNameFamilyType* pQtFtype = pFtnc->GetQtNameFamilyType();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pQtFtype, L"pQtFtype为空!", L"paramodel", L"2024-02-20");
    std::wstring strName = pQtFtype->name();
    OwnerPtr<IParameter> nameParameter = pParamBehavior->GetParameterByUid(PARAMETER_UID(ElementNameBuiltInParameter));
    if (!nameParameter)
        return false;
    IFamilyType* pSubFamilyType = nullptr;
    if (IInstanceType* instanceType = quick_cast<IInstanceType>(pickedType))
    {
        if (instanceType->IsSub())
        {
            gcmp::IFamily* pTopFamily = quick_cast<gcmp::IFamily>(m_wpDoc->GetElement(instanceType->GetTopFamilyId()));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pTopFamily, L"获取嵌套构件主构件信息为空", L"paramodel", L"2024-02-20");
            pSubFamilyType = pTopFamily->GetSubFamilyTypeBySubInstanceType(instanceType);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pSubFamilyType, L"获取不到pSubFamilyType", L"paramodel", L"2024-02-20");
        }
        else
        {
            IFamily* family = quick_cast<IFamily>(instanceType->GetFamily());
            DBG_WARN_AND_RETURN_FALSE_UNLESS(family, L"获取不到Family", L"paramodel", L"2024-02-20");
            IFamilyType* pFamilyType = family->GetFamilyTypeByName(nameParameter->GetValueAsString());
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyType, L"获取不到FamilyType", L"paramodel", L"2024-02-20");

            if (nameParameter->GetValueAsString() != strName)
            {
                // FamilyType的名称也需要修改
                pFamilyType->SetName(strName);
            }
        }
    }
    else if (IGenericType* pGenType = quick_cast<IGenericType>(pickedType))
    {
    }
    else
    {
        DBG_WARN_AND_RETURN_FALSE_UNLESS(false, L"请添加相应的类型处理", L"paramodel", L"2024-02-20");
    }

    if (nameParameter->GetValueAsString() != strName)
    {
        nameParameter->SetValueAsString(strName);
        IElementParameters* pElemParams = pickedType->GetElementParameters();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pElemParams, L"获取不到pElemParams", L"paramodel", L"2024-02-20");
        pElemParams->SetParameter(nameParameter.get());
    }

    // 更新参数列表
    std::wstring strDefaultGroup = GBMP_TR(L"基本属性");
    std::wstring strUndefinedGroup = GBMP_TR(L"参数列表");      // 未分组的参数放在这个组下
    const IParameterGroupsFilter* pGroupsFilter = IParameterGroupsFilter::GetParameterGroupsFilter();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pGroupsFilter != nullptr, L"pGroupsFilter为空", L"paramodel", L"2024-02-20");
    for (int loop = 0; loop < (int)m_vecDisplayedParameters.size(); ++loop)
    {
        const OwnerPtr<IParameter>& originParam = m_vecDisplayedParameters.at(m_vecParametersOrder.at(loop));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(originParam, L"获取不到originParam", L"paramodel", L"2024-02-20");

        const IParameterDefinition* paramDef = originParam->GetParameterDefinition();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(paramDef, L"获取不到paramDef", L"paramodel", L"2024-02-20");

        std::wstring groupName = pGroupsFilter->GetGroupName(paramDef);
        if (groupName == strDefaultGroup) groupName = strUndefinedGroup;

        gnuf::NameValuePairBlock* nvpb = hasPropertyGroup(m_pNameValuePairs, groupName);
        if (!nvpb)
            continue;
        gnuf::Item* pItem = hasPropertyItem(m_pNameValuePairs, groupName, paramDef->GetName());
        if (pItem)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(pItem->parent(), L"pItem->parent()为空!", L"paramodel", L"2024-02-20");
            DBG_WARN_AND_CONTINUE_UNLESS(pItem->parent()->info(), L"pItem->parent()->info()为空!", L"paramodel", L"2024-02-20");
            QString strParamName = QString::fromStdWString(pItem->parent()->info()->caption());

            std::wstring paraName = paramDef->GetName();
            const UniIdentity &uid = paramDef->GetUid();
            if (uid.HasSameValue(PARAMETER_UID(ProfileBreadthBuiltInParameter))
                || uid.HasSameValue(PARAMETER_UID(ProfileBreadthOffsetBuiltInParameter))
                || uid.HasSameValue(PARAMETER_UID(ProfileBreadthPart1BuiltInParameter))
                || uid.HasSameValue(PARAMETER_UID(ProfileHeightBuiltInParameter))
                || uid.HasSameValue(PARAMETER_UID(ProfileHeightPart1BuiltInParameter))
                || uid.HasSameValue(PARAMETER_UID(ProfileHeightPart2BuiltInParameter))
                || uid.HasSameValue(PARAMETER_UID(ProfileHeightPart3BuiltInParameter))
                )
            {
                if (paraName.find(L"异形截面") != std::wstring::npos)
                {
                    StringUtil::ReplaceAll(paraName, L"异形截面", L"");
                }
            }
            /*if (uid.HasSameValue(PARAMETER_UID(EngineeringProcess)))
            {
            continue;
            }*/
            QString strInternalParamName = QString::fromStdWString(paraName);
            DBG_WARN_AND_CONTINUE_UNLESS(strParamName.compare(strInternalParamName) == 0, L"参数名不匹配", L"paramodel", L"2024-02-20");
        }

        //从界面读取参数值
        OwnerPtr<IParameter> newParam = originParam->Clone();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(newParam, L"获取不到newParam", L"paramodel", L"2024-02-20");
        if (!UpdateParameterFromItem(newParam.get(), pItem))
            return false;
        //用参数验证器 对类型参数对话框的参数验证
        if (const IParameterValidator* pValidator = originParam->GetValidator())
        {
            std::wstring errMsg;
            if (!pValidator->Validate(newParam.get(), pickedType, &errMsg))
            {
                UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), errMsg, (int)UiCommonDialog::ButtonType::OK);
                return false;
            }
        }
        //设置参数
        std::wstring errMsg;
        if (!pParamBehavior->SetParameter(newParam.get(), &errMsg))
        {
            UiCommonDialog::ShowMessageBox(GBMP_TR(L"发生错误"), errMsg, int(UiCommonDialog::ButtonType::OK));
            return false;
        }

        // Type类型中，修改了类型参数，需要同时修改pSubFamilyType中的参数值
        if (pSubFamilyType)
        {
            std::vector<OwnerPtr<IParameter>> familyParameters = pSubFamilyType->GetFamilyParameters();
            auto findIter = std::find_if(familyParameters.begin(), familyParameters.end(), [&](const OwnerPtr<IParameter>& parameter) {return parameter->GetParameterDefinitionUid() == newParam->GetParameterDefinitionUid(); });
            if (findIter != familyParameters.end())
            {
                OwnerPtr<IParameter>& familyParameter = *findIter;

                const IParameterValueStorage* pParameterValue = newParam->GetParameterValueStorage();
                DBG_WARN_AND_CONTINUE_UNLESS(pParameterValue, L"pParameterValue为空", L"paramodel", L"2024-02-20");

                familyParameter->SetParameterValueStorage(pParameterValue->Clone());
                pSubFamilyType->SetFamilyParameter(m_wpDoc.Get(), familyParameter.get());
            }
        }
    }

    return true;
}

void gfam::FamilyNameValuePairsComponent::onFamilyTypeNameChanged(const std::wstring & typeName)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");

    DBG_WARN_AND_RETURN_VOID_UNLESS(s_familyTypeComponentBuilder->GetFamilyTypes(), L"s_familyTypeComponentBuilder->GetFamilyTypes()为空", L"paramodel", L"2024-02-20");
    gnuf::FamilyType* pCurType = s_familyTypeComponentBuilder->GetFamilyTypes()->currentFamilyType();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurType, L"pCurType is nullptr", L"paramodel", L"2024-02-20");

    std::wstring newTypeName = StringUtil::TrimSpace(typeName);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurType->nodeInfo(0), L"pCurType->nodeInfo(0) is nullptr", L"paramodel", L"2024-02-20");
    pCurType->setInfo(0, gnuf::Info(newTypeName, newTypeName, pCurType->nodeInfo(0)->iconDir()));
    s_familyTypeComponentBuilder->GetFamilyTypes()->setCurrentFamilyType(pCurType, false);

    gnuf::TreeNode* pParentNode = pCurType->parentNode();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParentNode, L"pParentNode is nullptr", L"paramodel", L"2024-02-20");

    pParentNode->sort(true);

    IType* pType = quick_cast<IType>(m_wpDoc->GetElement(pCurType->userData().cast<ItemInfo>().TypeId));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pType, L"pType is nullptr", L"paramodel", L"2024-02-20");

    OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改构件类型名称"), true);
    DBG_WARN_AND_RETURN_VOID_UNLESS(opTransaction, L"opTransaction is nullptr", L"paramodel", L"2024-02-20");

    gcmp::IElementParameters* pParamBehavior = pType->GetElementParameters();
    if (!pParamBehavior)
        return;

    // 更新"名称"参数
    OwnerPtr<IParameter> nameParameter = pParamBehavior->GetParameterByUid(PARAMETER_UID(ElementNameBuiltInParameter));
    DBG_WARN_AND_RETURN_VOID_UNLESS(nameParameter, L"获取内置的名称参数为空", L"paramodel", L"2024-02-20");
    if (IInstanceType* instanceType = dynamic_cast<IInstanceType*>(pType))
    {
        if (!instanceType->IsSub())
        {
            IFamily* family = quick_cast<IFamily>(instanceType->GetFamily());
            DBG_WARN_AND_RETURN_VOID_UNLESS(family, L"获取不到Family", L"paramodel", L"2024-02-20");
            IFamilyType* pFamilyType = family->GetFamilyTypeByName(nameParameter->GetValueAsString());
            DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType, L"获取不到FamilyType", L"paramodel", L"2024-02-20");

            if (nameParameter->GetValueAsString() != newTypeName)
            {
                // FamilyType的名称也需要修改
                pFamilyType->SetName(newTypeName);
            }
        } 
    }
    nameParameter->SetValueAsString(newTypeName);
    pParamBehavior->SetParameter(nameParameter.get());

    s_instanceNameValuePairsBuilder->Connect(false);
    opTransaction->Commit();
    s_instanceNameValuePairsBuilder->Connect(true);
}

void gfam::FamilyNameValuePairsComponent::BuildNameValuePairs(bool rebuild, bool fromElements)
{
    UpdateParameterOnTable();
}

bool gfam::FamilyNameValuePairsComponent::UpdatePropertyTableToFamily()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    IType* pType = quick_cast<IType>(m_wpDoc->GetElement(GetCurFamilyTypeId()));
    if (pType == nullptr)
        return false;

    IInstanceType* pInstanceType = quick_cast<IInstanceType>(pType);
    if (pInstanceType == nullptr || pInstanceType->IsSub())
        return false;

    OwnerPtr<IUserTransaction> ut = nullptr;
    if (!IUserTransaction::IsInUserTransaction(m_wpDoc.Get(), nullptr))
    {
        ut = IUserTransaction::Create(m_wpDoc.Get(), (GBMP_TR(L"同步类型参数值到FamilyType")));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(ut, L"ut为空", L"paramodel", L"2024-02-20");
    }
    {
        const IFamily* pFamily = pInstanceType->GetFamily();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamily != nullptr, L"pFamily为空！", L"paramodel", L"2024-02-20");

        DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType->GetBasicInformation(), L"获取不到pInstanceType->GetBasicInformation()", L"paramodel", L"2024-02-20");
        IFamilyType* pFamilyType = const_cast<IFamily*>(pFamily)->GetFamilyTypeByName(pInstanceType->GetBasicInformation()->GetName());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyType, L"获取不到FamilyType", L"paramodel", L"2024-02-20");

        // InstanceType中的参数值同步到FamilyType中
        IElementParameters* pElemParams = pType->GetElementParameters();
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyType, L"获取不到FamilyType", L"paramodel", L"2024-02-20");
        std::vector<OwnerPtr<IParameter>> typeParams = pElemParams->GetAllParameters();
        for (int i = 0; i < (int)typeParams.size(); ++i)
        {
            OwnerPtr<IParameter> opParam = typeParams[i]->Clone();
            pFamilyType->SetFamilyParameter(m_wpDoc.Get(), opParam.get());
        }
    }
    if (ut)
    {
        ut->Commit();
    }

    return true;
}

bool gfam::FamilyNameValuePairsComponent::UpdateParameterFromItem(gcmp::IParameter * param, gnuf::Item * pItem)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param获取不到", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pItem, L"pItem获取不到", L"paramodel", L"2024-02-20");

    const IParameterDefinition* pParamDef = param->GetParameterDefinition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pParamDef, L"pParamDef获取不到", L"paramodel", L"2024-02-20");
    IParameterDisplayManager* pParamDisplayMgr = IParameterDisplayManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pParamDisplayMgr, L"pParamDisplayMgr为空", L"paramodel", L"2024-02-20");
    const IParameterDisplay* paramDisplay = pParamDisplayMgr->GetParameterDisplay(pParamDef->GetUid());
    if (const IParameterDisplayDropdownList* dropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(paramDisplay))
    {
        gnuf::List* pList = nullptr;
        if (gnuf::Block* pBlock = pItem->cast<gnuf::Block>())
        {
            gnuf::Block::RawContents contents = pBlock->rawContents();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(contents.size() > 0, L"contents为空", L"paramodel", L"2024-02-20");

            gnuf::Item* firstItem = contents[0];
            if (firstItem && firstItem->type() == gnuf::EItemType::eList)
            {
                pList = firstItem->cast<gnuf::List>();
            }
        }
        else
        {
            pList = pItem->cast<gnuf::List>();
        }

        if (!pList)
            return false;

        std::wstring strCurValue = pList->Text();
        std::vector<ElementId> ids = { GetCurFamilyTypeId() };
        OwnerPtr<IParameterValueStorage> pvs = dropdownList->GetValueByDisplayString(m_wpDoc.Get(), strCurValue, ids);
        if (pvs)
        {
            const IParameterValueStorage* paramValue = param->GetParameterValueStorage();
            if (paramValue && !paramValue->HasSameValue(pvs.get()))
            {
                return param->SetParameterValueStorage(TransferOwnership(pvs));
            }
        }
        else
        {
            if (strCurValue.compare(L"更多材质") == 0)
            {
                std::wstring strToken(L"");
                std::wstring strLibIdList(L"");
                std::wstring strProductCode(L"");

                ElementId materialId = ElementId::InvalidID;
                UiCommonDialog::ShowMaterialSelectionDialog(m_wpDoc.Get(), materialId, strToken, strLibIdList, strProductCode);
                if (!materialId.IsValid())
                {
                    return false;
                }
                return param->SetValueAsElementId(materialId);
            }
        }
    }
    else if (dynamic_cast<const IParameterDisplayEditbox*>(paramDisplay) || dynamic_cast<const IParameterDisplayEditboxWithButton*>(paramDisplay))
    {
        gnuf::Block* pBlock = pItem->cast<gnuf::Block>();
        if (pBlock)
        {
            gnuf::Block::RawContents contents = pBlock->rawContents();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(contents.size() > 0, L"contents为空", L"paramodel", L"2024-02-20");

            gnuf::Item* firstItem = contents[0];
            if (firstItem && firstItem->type() == gnuf::EItemType::eText)
            {
                gnuf::Text *pText = firstItem->cast<gnuf::Text>();
                if (pText)
                {
                    QString textValue = QString::fromStdWString(pText->text());
                    textValue = textValue.trimmed();
                    // 滤除后缀
                    if (pParamDef->GetParameterTypeId() == PARAMETER_TYPE(Length))
                    {
                        textValue = textValue.left(textValue.indexOf(' '));
                    }
                    if (ParameterDisplayUtils::GetValueAsDisplayString(param) != textValue.toStdWString())
                    {
                        const std::wstring& originValue = ParameterDisplayUtils::GetValueAsDisplayString(param);
                        if (!ParameterDisplayUtils::SetValueFromDisplayString(param, textValue.toStdWString()))
                        {
                            return false;
                        }
                    }
                }
            }
        }
        else
        {
            gnuf::Text* pText = pItem->cast<gnuf::Text>();
            if (!pText)
                return false;

            QString strValue = QString::fromStdWString(pText->text());
            strValue = strValue.trimmed();
            // 滤除后缀
            if (pParamDef->GetParameterTypeId() == PARAMETER_TYPE(Length))
            {
                strValue = strValue.left(strValue.indexOf(' '));
            }
            if (ParameterDisplayUtils::GetValueAsDisplayString(param) != strValue.toStdWString())
            {
                const std::wstring& originValue = ParameterDisplayUtils::GetValueAsDisplayString(param);
                if (!ParameterDisplayUtils::SetValueFromDisplayString(param, strValue.toStdWString()))
                {
                    return false;
                }
            }
        }
    }
    else if (dynamic_cast<const IParameterDisplayCheckbox*>(paramDisplay))
    {
        gnuf::Check* pCheck = nullptr;

        if (gnuf::Block* pBlock = pItem->cast<gnuf::Block>())
        {
            gnuf::Block::RawContents contents = pBlock->rawContents();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(contents.size() > 0, L"contents为空", L"paramodel", L"2024-02-20");

            gnuf::Item* firstItem = contents[0];
            if (firstItem && firstItem->type() == gnuf::EItemType::eCheck)
            {
                pCheck = firstItem->cast<gnuf::Check>();
            }
        }
        else
        {
            pCheck = pItem->cast<gnuf::Check>();
        }

        if (!pCheck)
            return false;
        bool boolCurValue = pCheck->checkState() != gnuf::CheckStatus::UnChecked;
        if (param->GetValueAsBool() != boolCurValue)
        {
            return param->SetValueAsBool(boolCurValue);
        }
    }
    else if (IGnufParameterDisplayCustom* pDisplayCustom = GnufParameterDisplayCustomFactory::Get()->Find(pParamDef->GetUid()))
    {
        OwnerPtr<gcmp::IParameterValueStorage> pvs = pDisplayCustom->GetValue(m_wpDoc.Get(), {}, pItem);
        if (pvs)
        {
            const IParameterValueStorage* paramValue = param->GetParameterValueStorage();
            if (paramValue && !paramValue->HasSameValue(pvs.get()))
            {
                return param->SetParameterValueStorage(TransferOwnership(pvs));
            }
        }
    }
    else
    {
        if (!paramDisplay)
            return false;
        DBG_WARN_AND_RETURN_FALSE_UNLESS(false, L"未知类型的ParameterDisplay", L"paramodel", L"2024-02-20");
    }
    return true;
}

void gfam::FamilyNameValuePairsComponent::UpdateParameterOnTable()
{
    // 获取参数
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    IElement* pickedType = m_wpDoc->GetElement(GetCurFamilyTypeId());
    if (pickedType == nullptr)
        return;

    // 获取参数
    std::vector<OwnerPtr<IParameter>> allParams;

    IElementParameters* pEleBehavior = pickedType->GetElementParameters();

    if (pEleBehavior)
        allParams = pEleBehavior->GetAllParameters();

    //先清空待显示参数集
    if (!m_vecDisplayedParameters.empty())
        m_vecDisplayedParameters.clear();

    // 获取参数显示方式
    std::vector<const IParameterDefinition*> displayedParameterDefs;
    for (auto& eachParam : allParams)
    {
        DBG_WARN_AND_CONTINUE_UNLESS(eachParam, L"eachParam为空", L"paramodel", L"2024-02-20");
        const IParameterDefinition* paramDef = dynamic_cast<const IParameterDefinition*>(eachParam->GetParameterDefinition());
        DBG_WARN_AND_CONTINUE_UNLESS(paramDef, L"paramDef为空", L"paramodel", L"2024-02-20");
        const UniIdentity &uid = paramDef->GetUid();
        const IInstanceType* pInstanceType = quick_cast<IInstanceType>(pickedType);

        if (!eachParam->IsUserVisible())
        {
            continue;
        }
        if (uid.HasSameValue(PARAMETER_UID(RailingAllStructureDataBuiltInParameter))   // 暂时隐藏栏杆扶手样式
            || uid.HasSameValue(PARAMETER_UID(ElementNameBuiltInParameter))            // “名称”参数不显示
            || paramDef->GetParameterTypeId() == PARAMETER_TYPE(None))
        {
            continue;
        }
        displayedParameterDefs.push_back(paramDef);
        m_vecDisplayedParameters.push_back(eachParam->Clone());
    }

    // 获取参数所在组别名称，并排序
    const IParameterGroupsFilter* pGroupsFilter = IParameterGroupsFilter::GetParameterGroupsFilter();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pGroupsFilter != nullptr, L"pGroupsFilter为空", L"paramodel", L"2024-02-20");
    std::unordered_set<std::wstring> unorderGroupNames;
    FOR_EACH(paramDef, displayedParameterDefs)
    {
        std::wstring groupName = pGroupsFilter->GetGroupName(paramDef);
        unorderGroupNames.emplace(groupName);
    }
    std::vector<std::wstring> allGroupNames(unorderGroupNames.begin(), unorderGroupNames.end());
    std::vector<size_t> groupsOrder = pGroupsFilter->SortGroups(allGroupNames);                     //组别排序
    m_vecParametersOrder = pGroupsFilter->SortParameters(displayedParameterDefs);                   //参数排序

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pNameValuePairs != nullptr, L"m_pNameValuePairs为空", L"paramodel", L"2024-02-20");
    m_pNameValuePairs->clearContents();

    // 对话框中创建参数组
    std::wstring strDefaultGroup = GBMP_TR(L"基本属性");
    std::wstring strUndefinedGroup = GBMP_TR(L"参数列表");      // 未分组的参数放在这个组下
    if (allGroupNames.size() == 1 && allGroupNames.at(0) == strDefaultGroup)
    {
        addPropertyGroup(m_pNameValuePairs, strUndefinedGroup);
    }
    else
    {
        FOR_EACH_INDEX(idx, allGroupNames)
        {
            QString str = QString::fromStdWString(allGroupNames.at(groupsOrder.at(idx)));
            if (allGroupNames.at(groupsOrder.at(idx)) == strDefaultGroup)
            {
                addPropertyGroup(m_pNameValuePairs, strUndefinedGroup);
            }
            else
            {
                addPropertyGroup(m_pNameValuePairs, str.toStdWString());
            }
        }
    }

    // 把类型参数添加到所属的组别中
    for (int loop = 0; loop < (int)displayedParameterDefs.size(); ++loop)
    {
        const IParameterDefinition* paramDefinition = displayedParameterDefs.at(m_vecParametersOrder.at(loop));
        DBG_WARN_AND_CONTINUE_UNLESS(paramDefinition != nullptr, L"paramDefinition不能为空", L"paramodel", L"2024-02-20");

        DBG_WARN_AND_CONTINUE_UNLESS(m_vecDisplayedParameters.at(m_vecParametersOrder.at(loop)) != nullptr, L"m_vecDisplayedParameters.at(m_vecParametersOrder.at(loop))不能为空", L"paramodel", L"2024-02-20");
        OwnerPtr<IParameter> currentParam = m_vecDisplayedParameters.at(m_vecParametersOrder.at(loop))->Clone();
        DBG_WARN_AND_CONTINUE_UNLESS(currentParam != nullptr, L"currentParam不能为空", L"paramodel", L"2024-02-20");

        std::wstring groupName = pGroupsFilter->GetGroupName(paramDefinition);
        if (groupName == strDefaultGroup)
            groupName = strUndefinedGroup;

        gnuf::NameValuePairBlock* nvpb = hasPropertyGroup(m_pNameValuePairs, groupName);
        if (!nvpb)
            continue;

        std::wstring paraName = paramDefinition->GetName();
        const UniIdentity &uid = paramDefinition->GetUid();
        if (uid.HasSameValue(PARAMETER_UID(ProfileBreadthBuiltInParameter))
            || uid.HasSameValue(PARAMETER_UID(ProfileBreadthOffsetBuiltInParameter))
            || uid.HasSameValue(PARAMETER_UID(ProfileBreadthPart1BuiltInParameter))
            || uid.HasSameValue(PARAMETER_UID(ProfileHeightBuiltInParameter))
            || uid.HasSameValue(PARAMETER_UID(ProfileHeightPart1BuiltInParameter))
            || uid.HasSameValue(PARAMETER_UID(ProfileHeightPart2BuiltInParameter))
            || uid.HasSameValue(PARAMETER_UID(ProfileHeightPart3BuiltInParameter))
            )
        {
            if (paraName.find(L"异形截面") != std::wstring::npos)
            {
                StringUtil::ReplaceAll(paraName, L"异形截面", L"");
            }
        }        auto modifyAndBindStatus = GetParameterCanModifyAndBind(pickedType, currentParam.get());

        gnuf::Item* pItem = AddPropertyItemToBlock(
            m_wpDoc.Get(),
            nvpb, 
            *currentParam.get(), 
            GetCurFamilyTypeId(), 
            m_elementIds, 
            currentParam->GetParameterDefinitionId(), 
            false, 
            !modifyAndBindStatus.first,
            modifyAndBindStatus.second);
        DBG_WARN_AND_CONTINUE_UNLESS(pItem != nullptr, L"CPropertyItem添加失败", L"paramodel", L"2024-02-20");

    }

    m_pNameValuePairs->dumpContents();
}

void gfam::FamilyNameValuePairsComponent::onEditTypeDialogOkBtnClicked()
{
    if (m_familyNameComponent && m_familyNameComponent->GetQtNameFamilyType())
        onFamilyTypeNameChanged(m_familyNameComponent->GetQtNameFamilyType()->name());

    if (!IUserTransaction::IsInUserTransaction(m_wpDoc.Get(), nullptr))
    {
        m_upUserTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改构件属性"), true);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_upUserTransaction, L"m_upUserTransaction为空", L"paramodel", L"2024-02-20");
    }
    // 从列表界面修改类型参数更新到Element（提交事务)
    bool res = UpdatePropertyTableToElement();
    if (res)
    {
        if (m_upUserTransaction)
        {
            m_upUserTransaction->Commit();
        }
        UpdatePropertyTableToFamily();

        //类型参数修改后处理事件
        if (!m_modifiedTypeParamIds.empty())
        {
            m_modifiedTypeParamIds.clear();
        }
    }
    else
    {
        if (m_upUserTransaction)
        {
            m_upUserTransaction->Rollback();
            m_vecDisplayedParameters.clear();
            m_modifiedTypeParamIds.clear();
            m_vecParametersOrder.clear();
            UpdateParameterOnTable();
        }
    }
}

void gfam::FamilyNameValuePairsComponent::onEditTypeDialogCancelClicked()
{
}

void gfam::FamilyNameValuePairsComponent::quitTransaction()
{
    if (m_upUserTransaction)
    {
        m_upUserTransaction = nullptr;
    }
}

gcmp::ElementId gfam::FamilyNameValuePairsComponent::GetCurFamilyTypeId()
{
    gnuf::FamilyTypes* pFamilyTypes = s_familyTypeComponentBuilder->GetFamilyTypes();
    if (!pFamilyTypes)
        return ElementId::InvalidID;

    gnuf::FamilyType* pCurType = pFamilyTypes->currentFamilyType();
    if (!pCurType)
        return ElementId::InvalidID;

    return pCurType->userData().cast<ItemInfo>().TypeId;
}

gfam::FamilyTypeIntegratedComponent::FamilyTypeIntegratedComponent()
{
}

void gfam::FamilyTypeIntegratedComponent::BuildFamilyTypeComponent()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc, L"无效m_pDoc", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes, L"无效m_pFamilyTypes", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_elementIds.empty(), L"无效m_elementIds", L"paramodel", L"2024-02-20");

    m_pFamilyTypes->clearContents();
    const gcmp::IElement* pElement = m_pDoc->GetElement(m_elementIds[0]);
    if (!pElement)
    {
        return;
    }
    if (const gcmp::IModelView* pModelView = quick_cast<IModelView>(pElement))
    {
        ShowViewComponentType();
        return;
    }
    else
    {
        gnuf::FamilyTypeButton* familyTypeBtn = m_pFamilyTypes->familyTypeButton();
        DBG_WARN_AND_RETURN_VOID_UNLESS(familyTypeBtn, L"无效btn", L"paramodel", L"2024-02-20");

        const IElementBasicInformation* pBasicInformation = pElement->GetBasicInformation();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pBasicInformation, L"pBasicInformation为空", L"paramodel", L"2024-02-20");
        const IType* pType = pBasicInformation->GetType(); // 簇类型
        if (pType == nullptr)
        {
            std::wstring typeName = pBasicInformation->GetDefaultTypeName();
            if (typeName.empty())
            {
                gcmp::UniIdentity uid = pBasicInformation->GetCategoryUid();
                if (uid.IsValid())
                {
                    ICategoryLibrary* pCategoryLibrary = ICategoryLibrary::Get(m_pDoc);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pCategoryLibrary, L"pCategoryLibrary is nullptr", L"paramodel", L"2024-02-20");
                    const ICategory* pCategory = pCategoryLibrary->GetCategory(uid);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pCategory, L"pCategory is nullptr", L"paramodel", L"2024-02-20");

                    typeName = pCategory->GetName();
                }
            }

            const IGenericElement *pGenericElement = quick_cast<IGenericElement>(pElement);
            if (pGenericElement)
            {
                const IFamilyExternalForm *pFamilyExternalForm = quick_cast<IFamilyExternalForm>(pGenericElement->GetExternalObject());
                if (pFamilyExternalForm)
                {
                    typeName = L"导入SAT文件";
                }
            }

            gnuf::Info info(typeName, L"", L":/image/ModelView/View/3D/");
            familyTypeBtn->assignInfo(info);
            familyTypeBtn->setEnabled(false);
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->addFamilyTypeButton(), L"m_pFamilyTypes->addFamilyTypeButton() is nullptr", L"paramodel", L"2024-02-20");
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->editFamilyTypeButton(), L"m_pFamilyTypes->editFamilyTypeButton() is nullptr", L"paramodel", L"2024-02-20");
            m_pFamilyTypes->addFamilyTypeButton()->setEnabled(false);
            m_pFamilyTypes->editFamilyTypeButton()->setEnabled(false);
            return;
        }

        if (m_elementIds.size() > 1) // 多选的情况   
        {
            for (int idx = 0; idx < (int)m_elementIds.size(); ++idx)
            {
                if (!familyTypeBtn->info())
                {
                    continue;
                }

                gnuf::Info info(familyTypeBtn->info()->caption(), familyTypeBtn->info()->tooltip(), familyTypeBtn->info()->iconDir());

                const IElement* pSelElement = m_pDoc->GetElement(m_elementIds[idx]);
                if (pSelElement == nullptr)
                    return;

                if (!pSelElement->GetBasicInformation())
                {
                    return;
                }

                //  类别不同，显示多种
                if (pBasicInformation->GetCategoryUid() != pSelElement->GetBasicInformation()->GetCategoryUid())
                {
                    info.setCaption(multiCategoryText);
                    familyTypeBtn->assignInfo(info);
                    familyTypeBtn->setEnabled(false);
                    return;
                }

                const IType* pSelType = pSelElement->GetBasicInformation()->GetType();

                if (pType && pSelType)
                {
                    if (pType->GetElementId() != pSelType->GetElementId())
                    {
                        info.setCaption(multiTypeText);
                        familyTypeBtn->assignInfo(info);
                        return;
                    }
                }
                else if (!pType && !pSelType)
                {
                    return;
                }
                else
                {
                    info.setCaption(multiCategoryText);
                    familyTypeBtn->assignInfo(info);
                    familyTypeBtn->setEnabled(false);
                }


            }
        }

        ElementTypeGroups typeGroupVec;
        if (m_elementIds.size() >= 1)
        {
            const IInstance* pSelectInstance = quick_cast<const IInstance>(pElement);
            if (pSelectInstance)
            {
                if (pSelectInstance->GetSuperInstanceId().IsValid())
                {
                    const IElementBasicInformation* pBasicInfo = pSelectInstance->GetBasicInformation();
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pBasicInfo, L"基本信息组件为空", L"paramodel", L"2024-02-20");
                    IInstanceType* pInstanceType = quick_cast<IInstanceType>(pBasicInfo->GetType());
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pInstanceType, L"获取类型为空", L"paramodel", L"2024-02-20");

                    const ElementId& topFamilyId = pInstanceType->GetTopFamilyId();
                    const IFamily* pTopFamily = quick_cast<IFamily>(m_pDoc->GetElement(topFamilyId));
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pTopFamily, L"获取主构件为空", L"paramodel", L"2024-02-20");
                    std::vector<const IFamilyType*> pFamilyTypes = pTopFamily->GetAllSubFamilyTypesBySubInstanceType(pInstanceType);
                    std::vector<ElementTypeInfo> typeInfoVec;
                    FOR_EACH(pFamilyType, pFamilyTypes)
                    {
                        DBG_WARN_AND_CONTINUE_UNLESS(pFamilyType, L"族类型为空", L"paramodel", L"2024-02-20");
                        ElementTypeInfo newTypeInfo = std::make_tuple(
                            pInstanceType->GetElementId().GetId()
                            , pFamilyType->GetName()
                            , L":/PropertyDemo/Images/陶瓷墙.jpg"); //从PropertyPallete.cpp 直接拷贝过来， 应当换掉
                        typeInfoVec.push_back(std::move(newTypeInfo));
                    }

                    ElementTypeGroup newTypeGroup = std::make_tuple(std::make_tuple(pInstanceType->GetElementId().AsInt64(), pTopFamily->GetSubFamilyNameBySubInstanceType(pInstanceType), L""), std::move(typeInfoVec));
                    typeGroupVec.push_back(std::move(newTypeGroup));
                }
                else
                {
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement->GetBasicInformation(), L"pElement->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
                    const UniIdentity& selectElementCategroyUid = pElement->GetBasicInformation()->GetCategoryUid();

                    std::vector<const IFamily*> similarFamilies;
                    std::vector<IFamily*> allFamilies = IFamily::GetAllFamilies(m_pDoc);
                    FOR_EACH(pFamily, allFamilies)
                    {
                        DBG_WARN_AND_CONTINUE_UNLESS(pFamily&&pFamily->GetBasicInformation(), L"族为空", L"paramodel", L"2024-02-20");
                        if (pFamily->GetBasicInformation()->GetCategoryUid() != selectElementCategroyUid)
                            continue;

                        if (IsValidFamilyForInstance(pSelectInstance, pFamily))
                        {
                            similarFamilies.push_back(pFamily);
                        }
                    }

                    for (auto itFam : similarFamilies)
                    {
                        std::vector<ElementTypeInfo> typeInfoVec;
                        auto typeList = itFam->GetInstanceTypes();
                        for (auto itType = typeList.begin(); itType != typeList.end(); ++itType)
                        {
                            DBG_WARN_AND_CONTINUE_UNLESS((*itType) && (*itType)->GetBasicInformation(), L"类型实例为空", L"paramodel", L"2024-02-20");
                            ElementTypeInfo newTypeInfo = std::make_tuple(
                                (*itType)->GetBasicInformation()->GetElementId().GetId()
                                , (*itType)->GetBasicInformation()->GetName()
                                , L":/PropertyDemo/Images/陶瓷墙.jpg"); //从PropertyPallete.cpp 直接拷贝过来， 应当换掉
                            typeInfoVec.push_back(std::move(newTypeInfo));
                        }
                        DBG_WARN_AND_CONTINUE_UNLESS(itFam->GetBasicInformation(), L"itFam->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
                        ElementTypeGroup newTypeGroup = std::make_tuple(std::make_tuple(itFam->GetElementId().AsInt64(), itFam->GetBasicInformation()->GetName(), L""), std::move(typeInfoVec));
                        typeGroupVec.push_back(std::move(newTypeGroup));
                    }
                }
            }
            if (const ILinkElementProxy* pLinkElementProxy = quick_cast<ILinkElementProxy>(pElement))
            {
                std::vector<ElementTypeInfo> typeInfoVec;
                DBG_WARN_AND_RETURN_VOID_UNLESS(pType->GetBasicInformation(), L"pType->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
                ElementTypeInfo newTypeInfo = std::make_tuple(pType->GetBasicInformation()->GetElementId().GetId()
                    , pType->GetBasicInformation()->GetName(), L"");
                typeInfoVec.push_back(std::move(newTypeInfo));
                ElementTypeGroup newTypeGroup = std::make_tuple(std::make_tuple(pType->GetElementId().AsInt64(), pType->GetBasicInformation()->GetName(), L""), std::move(typeInfoVec));
                typeGroupVec.push_back(std::move(newTypeGroup));
            }

            int groupIdx = 0;
            for (auto& typeGroup : typeGroupVec)
            {
                auto groupInfo = std::get<0>(typeGroup);

                std::wstring typeIcon = std::get<2>(groupInfo);
                gnuf::Family* pFamily = m_pFamilyTypes->addFamily();
                pFamily->setUserData(gcmp::Any(std::get<0>(groupInfo)));
                pFamily->setInfo(0, gnuf::Info(std::get<1>(groupInfo), std::get<1>(groupInfo), typeIcon));
                pFamily->setSelectable(false);

                int typeIdx = 0;
                auto typeInfoVec = std::get<1>(typeGroup);
                for (auto& typeInfo : typeInfoVec)
                {
                    ItemInfo info(ElementId(std::get<0>(typeInfo)), false, -1);
                    gnuf::FamilyType* pFamilyType = m_pFamilyTypes->addFamilyType(pFamily);
                    pFamilyType->setUserData(info);
                    pFamilyType->setInfo(0, gnuf::Info(std::get<1>(typeInfo), std::get<1>(typeInfo), typeIcon));

                    if (pType && pType->GetBasicInformation())
                    {
                        if (pType->GetBasicInformation()->GetElementId().GetId() == std::get<0>(typeInfo)
                            && pType->GetBasicInformation()->GetName() == std::get<1>(typeInfo))
                        {
                            m_pFamilyTypes->setCurrentFamilyType(pFamilyType, false);
                        }
                    }
                    else
                    {
                        if (std::get<0>(groupInfo) == std::get<0>(typeInfo)
                            && std::get<1>(groupInfo) == std::get<1>(typeInfo))
                        {
                            m_pFamilyTypes->setCurrentFamilyType(pFamilyType, false);
                        }
                    }

                }
            }
        }
    }

    SetStatusOfAddAndModifyButton();
    gnuf::TreeBoard* pBoard = m_pFamilyTypes->familyTree();
    pBoard->expandAll();
}

void gfam::FamilyTypeIntegratedComponent::SetDocument(gcmp::IDocument * pDoc)
{
    if (pDoc == m_pDoc)
    {
        return;
    }
    m_pDoc = pDoc;
}

void gfam::FamilyTypeIntegratedComponent::onAddFamilyType(gnuf::FamilyType * pFamilyType)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType != nullptr, L"pFamilyTypes为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc != nullptr, L"m_pDoc为空", L"paramodel", L"2024-02-20");

    ElementId typeId = pFamilyType->userData().cast<ItemInfo>().TypeId;
    IType* pCurElementType = quick_cast<IType>(m_pDoc->GetElement(ElementId(typeId)));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurElementType, L"pCurElementType不能为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurElementType->GetBasicInformation(), L"pCurElementType->GetBasicInformation()不能为空", L"paramodel", L"2024-02-20");

    // 1. Pop up the dialog to name a new family type.    
    std::wstring newFamilyName = pCurElementType->GetBasicInformation()->GetName() + L"_新建";
    if (!m_familyNameComponent)
    {
        m_familyNameComponent = NEW_AS_OWNER_PTR(FamilyTypeNameComponent, this, newFamilyName, false);
    }

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameComponent->GetQtNameFamilyType(), L"m_familyNameComponent->GetQtNameFamilyType()不能为空", L"paramodel", L"2024-02-20");
    m_familyNameComponent->GetQtNameFamilyType()->setName(newFamilyName);
    if (1 == m_familyNameComponent->GetQtNameFamilyType()->popup(GBMP_TR(L"新建类型"))) {
        return;
    }
}

void gfam::FamilyTypeIntegratedComponent::onEditFamilyType(gnuf::FamilyType * pFamilyType)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType != nullptr, L"pFamilyTypes为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType->isLeaf(), L"pFamilyTypes should be a leaf node", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc != nullptr, L"m_pDoc为空", L"paramodel", L"2024-02-20");

    //修改构件类型按钮时发出信号 通知Action类型更新
    //NotifyActionToUpdate(m_pDoc, m_elementIds, STR_FAM_EVENT_TYPE_MODIFY_PRE_COMPONENT_TYPE);

    ElementId typeId = pFamilyType->userData().cast<ItemInfo>().TypeId;
    IElement* pElementType = m_pDoc->GetElement(typeId);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementType, L"pElementType不能为空", L"paramodel", L"2024-02-20");

    if (m_familyNameValuePairsBuilder == nullptr)
    {
        IElementBasicInformation* pBasicInfo = pElementType->GetBasicInformation();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pBasicInfo != nullptr, L"pBasicInfo为空", L"paramodel", L"2024-02-20");
        m_familyNameValuePairsBuilder = NEW_AS_OWNER_PTR(FamilyNameValuePairsComponent, pBasicInfo->GetName());
    }

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameValuePairsBuilder, L"m_familyNameValuePairsBuilder不能为空", L"paramodel", L"2024-02-20");
    m_familyNameValuePairsBuilder->SetDocument(m_pDoc);

    DBG_WARN_AND_RETURN_VOID_UNLESS(pElementType->GetBasicInformation(), L"pElementType->GetBasicInformation()不能为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameValuePairsBuilder->GetFamilyTypeNameComponent(), L"m_familyNameValuePairsBuilder->GetFamilyTypeNameComponent()不能为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameValuePairsBuilder->GetFamilyTypeNameComponent()->GetQtNameFamilyType(), L"m_familyNameValuePairsBuilder->GetFamilyTypeNameComponent()->GetQtNameFamilyType()不能为空", L"paramodel", L"2024-02-20");
    m_familyNameValuePairsBuilder->GetFamilyTypeNameComponent()->GetQtNameFamilyType()->setName(pElementType->GetBasicInformation()->GetName());
    IElementParameters* pElementParameter = pElementType->GetElementParameters();
    if (pElementParameter)
    {
        IParameterDefinitionLibrary* pParamDefLib = IParameterDefinitionLibrary::Get(m_pDoc);
        if (pParamDefLib && !pElementParameter->IsParameterModifiable(pParamDefLib->GetParameterDefinitionIdByUid(PARAMETER_UID(ElementNameBuiltInParameter))))
        {
            m_familyNameValuePairsBuilder->GetFamilyTypeNameComponent()->GetQtNameFamilyType()->setRenameEnabled(false);
        }
    }
    m_familyNameValuePairsBuilder->SetElementIds({ typeId });
    m_familyNameValuePairsBuilder->BuildNameValuePairs(true);

    std::tuple<bool, ePreviewType> result = GnufParameterPreviewUtils::IsCanPreviewParameter(m_pDoc, typeId);
    bool canPreview = std::get<0>(result);
    if (canPreview && m_familyNameValuePairsBuilder->GetQtEditFamilyType() && m_familyNameValuePairsBuilder->GetQtEditFamilyType()->previewGeometry())
    {
        m_familyNameValuePairsBuilder->GetQtEditFamilyType()->previewGeometry()->hide();
    }
    m_familyNameValuePairsBuilder->GetQtEditFamilyType()->popup(GBMP_TR(L"类型参数"), GnufParameterPreviewUtils::GetParentWidget(), canPreview, std::get<1>(result));
}

void gfam::FamilyTypeIntegratedComponent::onCurrentFamilyTypeChanged(gnuf::FamilyTypes *, gnuf::FamilyType * oldType, gnuf::FamilyType * curType)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes != nullptr, L"pFamilyTypes为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc != nullptr, L"m_pDoc为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_elementIds.empty() == false, L"SelectedElements为空", L"paramodel", L"2024-02-20");

    ItemInfo info = curType->userData().cast<ItemInfo>();
    IElement* pElement = m_pDoc->GetElement(m_elementIds[0]);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"pElement不能为空", L"paramodel", L"2024-02-20");
    const Info* pNodeInfo = curType->nodeInfo(0);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pNodeInfo, L"获取节点信息为空", L"paramodel", L"2024-02-20");

    bool isChangedType = false;

    if (m_upUserTransaction == nullptr)
    {
        m_upUserTransaction = IUserTransaction::Create(m_pDoc, GBMP_TR(L"切换族类型"), true);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_upUserTransaction, L"m_upUserTransaction为空", L"paramodel", L"2024-02-20");
    }
    if (m_upUserTransaction->IsStarted() == false)
    {
        m_upUserTransaction->Start();
    }

    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement->GetBasicInformation(), L"无法获取到有效的pElement->GetBasicInformation()", L"paramodel", L"2024-02-20");
    IType* pOldType = pElement->GetBasicInformation()->GetType();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pOldType, L"无法获取到有效的ElementType", L"paramodel", L"2024-02-20");
    IInstanceType* pInstanceType = quick_cast<IInstanceType>(pOldType);
    if (pInstanceType && pInstanceType->IsSub())
    {
        const std::vector<Int64>& pSubFamilyIdPath = pInstanceType->GetSubFamilyIdPath();
        FOR_EACH(selEle, m_elementIds)
        {
            IInstance* pSubInstance = quick_cast<IInstance>(m_pDoc->GetElement(selEle));
            DBG_WARN_AND_CONTINUE_UNLESS(pSubInstance && pSubInstance->GetSuperInstanceId().IsValid(), L"pSubInstance不能为空", L"paramodel", L"2024-02-20");

            //PS: 这里还是以单个element传到behavior去进行实际切换， 
            //    是因为预设参数的相关逻辑不好处理，待属性面板重构后， 
            //    决定是否将选择集整体传入SwitchTypeOfElement接口。 -- zhangl-al
            //isChangedType = pTypeBehavior->SwitchTypeOfElement(pElement);
            isChangedType = NestedInstanceUtils::SwitchSubInstanceToType(pSubInstance, pSubFamilyIdPath, pNodeInfo->caption());

            if (s_instanceNameValuePairsBuilder->m_tmpPreSetElementId.IsValid())
            {
                IPresetParameterManager* pPreSetMgr = IPresetParameterManager::Get(m_pDoc);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pPreSetMgr, L"pPreSetMgr为空", L"paramodel", L"2024-02-20");

                Int32 categorySecondkey = pPreSetMgr->GetPresetValuesGroupId(pSubInstance);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pSubInstance->GetBasicInformation(), L"pSubInstance->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
                if (pPreSetMgr->SetPresetType(pSubInstance->GetBasicInformation()->GetCategoryUid(), categorySecondkey, pSubInstance->GetBasicInformation()->GetTypeId()))
                    isChangedType = true;
            }
        }
    }
    else
    {
        IType* pNewType = nullptr;
        DBG_WARN_AND_RETURN_VOID_UNLESS(pOldType->GetBasicInformation(), L"pOldType->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
        std::vector<IElement*> allElement = m_pDoc->GetElementsByCategory(pOldType->GetBasicInformation()->GetCategoryUid());
        FOR_EACH(itemEle, allElement)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(itemEle, L"itemEle不能为空", L"paramodel", L"2024-02-20");
            if (itemEle->GetElementId() == info.TypeId)
            {
                pNewType = quick_cast<IType>(itemEle);
                break;
            }
        }
        DBG_WARN_AND_RETURN_VOID_UNLESS(pNewType, L"无法在同一个Category下找到目标类型", L"paramodel", L"2024-02-20");

        s_instanceNameValuePairsBuilder->Connect(false);
        FOR_EACH(selEle, m_elementIds)
        {
            IElement* pElement = m_pDoc->GetElement(selEle);
            DBG_WARN_AND_CONTINUE_UNLESS(pElement, L"pElement不能为空", L"paramodel", L"2024-02-20");

            //PS: 这里还是以单个element传到behavior去进行实际切换， 
            //    是因为预设参数的相关逻辑不好处理，待属性面板重构后， 
            //    决定是否将选择集整体传入SwitchTypeOfElement接口。 -- zhangl-al

            IInstance* pInstance = quick_cast<IInstance>(pElement);
            if (!pInstance)
                continue;

            isChangedType = SwitchTypeOfElement(pNewType, pElement);
            if (s_instanceNameValuePairsBuilder->m_tmpPreSetElementId.IsValid())
            {
                IPresetParameterManager* pPreSetMgr = IPresetParameterManager::Get(m_pDoc);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pPreSetMgr, L"pPreSetMgr为空", L"paramodel", L"2024-02-20");

                Int32 categorySecondkey = pPreSetMgr->GetPresetValuesGroupId(pElement);
                if (pPreSetMgr->SetPresetType(pElement->GetBasicInformation()->GetCategoryUid(), categorySecondkey, pElement->GetBasicInformation()->GetTypeId()))
                    isChangedType = true;
            }
        }

    }
    
    //标记不需要更新整个属性表，避免提交事务导致更新
    s_instanceNameValuePairsBuilder->SetNeedUpdate(false);
    if (isChangedType)
    {
        m_upUserTransaction->Commit();
    }
    else
    {
        m_upUserTransaction->Rollback();
    }
    m_upUserTransaction = nullptr;

    //更新属性表
    s_instanceNameValuePairsBuilder->BuildNameValuePairs(s_instanceNameValuePairsBuilder->IsNeedUpdate());
    SetStatusOfAddAndModifyButton();
    s_instanceNameValuePairsBuilder->Connect(true);

    //各种参数都更新好了，再更新可视化。
    s_instanceNameValuePairsBuilder->UpdateViewVisual();
}

//直接点击"新建类别"按钮并确定时调用
void gfam::FamilyTypeIntegratedComponent::onFamilyTypeNameChanged(const std::wstring & name)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes != nullptr, L"pFamilyTypes为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc != nullptr, L"m_pDoc为空", L"paramodel", L"2024-02-20");

    gnuf::FamilyType* pFamilyType = m_pFamilyTypes->currentFamilyType();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyType, L"pFamilyType为空", L"paramodel", L"2024-02-20");

    gcmp::ElementId typeId = pFamilyType->userData().cast<ItemInfo>().TypeId;
    gcmp::IType* pCurElementType = gcmp::quick_cast<gcmp::IType>(m_pDoc->GetElement(gcmp::ElementId(typeId)));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurElementType, L"pCurElementType不能为空", L"paramodel", L"2024-02-20");

    std::wstring newFamilyName = gcmp::StringUtil::TrimSpace(name);
    gcmp::ElementId idNewType;
    gcmp::OwnerPtr<gcmp::IUserTransaction> ut = gcmp::IUserTransaction::Create(m_pDoc, (GBMP_TR(L"新建族类型")));
    DBG_WARN_AND_RETURN_VOID_UNLESS(ut, L"ut为空", L"paramodel", L"2024-02-20");

    {
        gcmp::IInstanceType* pInstanceType = gcmp::quick_cast<gcmp::IInstanceType>(pCurElementType);
        if (pInstanceType != nullptr)
        {
            if (pInstanceType->IsSub())
            {
                DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc, L"当前文档为空", L"paramodel", L"2024-02-20");
                IFamily* pTopFamily = quick_cast<IFamily> (m_pDoc->GetElement(pInstanceType->GetTopFamilyId()));
                DBG_WARN_AND_RETURN_VOID_UNLESS(pTopFamily, L"pFamily为空！", L"paramodel", L"2024-02-20");
                const IFamilyType* pCurrentFamilyType = pTopFamily->GetSubFamilyTypeBySubInstanceType(pInstanceType);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentFamilyType, L"获取当前组类型为空", L"paramodel", L"2024-02-20");
                OwnerPtr<IFamilyType> opNewFamilyType = IFamilyType::Create(name, pCurrentFamilyType);
                DBG_WARN_AND_RETURN_VOID_UNLESS(opNewFamilyType, L"新构件类型创建失败", L"paramodel", L"2024-02-20");
                pTopFamily->AddSubFamilyType(pInstanceType->GetSubFamilyIdPath(), opNewFamilyType.get());
                IInstanceType* pNewInstanceType = pTopFamily->CreateSubInstanceType(pInstanceType->GetSubFamilyIdPath(), name);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pNewInstanceType && pNewInstanceType->GetBasicInformation(), L"实例类型创建失败", L"paramodel", L"2024-02-20");
                idNewType = pNewInstanceType->GetBasicInformation()->GetElementId();
            }
            else
            {
                gcmp::IFamily* pFamily = pInstanceType->GetFamily();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pFamily != nullptr, L"pFamily为空！", L"paramodel", L"2024-02-20");

                DBG_WARN_AND_RETURN_VOID_UNLESS(pInstanceType->GetBasicInformation() != nullptr, L"pInstanceType->GetBasicInformation()为空！", L"paramodel", L"2024-02-20");
                const gcmp::IFamilyType* pOldFamilyType = pFamily->GetFamilyTypeByName(pInstanceType->GetBasicInformation()->GetName());
                DBG_WARN_AND_RETURN_VOID_UNLESS(pOldFamilyType != nullptr, L"FamilyType为空！", L"paramodel", L"2024-02-20");

                OwnerPtr<IFamilyType> newFamilyType = IFamilyType::Create(newFamilyName, pOldFamilyType);
                DBG_WARN_AND_RETURN_VOID_UNLESS(newFamilyType != nullptr, L"newFamilyType为空！", L"paramodel", L"2024-02-20");
                pFamily->AddFamilyType(newFamilyType.get());

                IInstanceType* pNewInstanceType = pFamily->GetInstanceTypeByName(newFamilyName);
                if (!pNewInstanceType)
                    pNewInstanceType = pFamily->CreateInstanceType(newFamilyName);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pNewInstanceType != nullptr && pNewInstanceType->GetBasicInformation(), L"pNewInstanceType为空！", L"paramodel", L"2024-02-20");
                idNewType = pNewInstanceType->GetBasicInformation()->GetElementId();
            }
        }
        else
        {
            const ICopyOperator* pCopyOperator = ICopyOperator::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCopyOperator != nullptr, L"pCopyOperator为空！", L"paramodel", L"2024-02-20");

            IType* pNewType = quick_cast<IType>(pCopyOperator->CopyElement(pCurElementType));
            DBG_WARN_AND_RETURN_VOID_UNLESS(pNewType != nullptr, L"pNewType为空！", L"paramodel", L"2024-02-20");

            DBG_WARN_AND_RETURN_VOID_UNLESS(pNewType->GetBasicInformation(), L"pNewType->GetBasicInformation()为空！", L"paramodel", L"2024-02-20");
            idNewType = pNewType->GetBasicInformation()->GetElementId();
            pNewType->GetBasicInformation()->SetName(newFamilyName);
        }
        s_instanceNameValuePairsBuilder->Connect(false);
        if (ut)
            ut->Commit();
        s_instanceNameValuePairsBuilder->Connect(true);

        // 2. Set this new family type as the current one.
        gnuf::TreeNode* pRoot = pFamilyType;
        while (!pRoot->isRoot())
        {
            pRoot = pRoot->parentNode();
        }
        gnuf::FamilyType* pNewFamilyTypeItem = m_pFamilyTypes->addFamilyType(pRoot);
        // 以下代码会修改当前实例类型，可根据具体需求去除以下代码段
        // 2. Set this new family type as the current one.
        ItemInfo info(idNewType, false, -1);
        pNewFamilyTypeItem->setUserData(info);
        pNewFamilyTypeItem->setInfo(0, gnuf::Info(newFamilyName, newFamilyName, iconPath));
        m_pFamilyTypes->setCurrentFamilyType(pNewFamilyTypeItem);

        const IEditMode* pEditMode = IEditMode::GetTopActiveEditMode(m_pDoc);
        if (pEditMode)
        {
            IFamilySketch2D* pCurSketch = FamilyElementUtils::GetElement<IFamilySketch2D>(m_pDoc, pEditMode->GetEditingElementId());
            if (pCurSketch)
            {
                IElement *pElement = m_pDoc->GetElement(pCurSketch->GetOwnerFormId());
                DBG_WARN_AND_RETURN_VOID_UNLESS(pElement != nullptr, L"pElement为空！", L"paramodel", L"2024-02-20");

                IElementParameters* pElementParameters = pElement->GetElementParameters();
                DBG_WARN_AND_RETURN_VOID_UNLESS(pElementParameters != nullptr, L"pElementParameters为空！", L"paramodel", L"2024-02-20");
                OwnerPtr<IParameter> param1 = pElementParameters->GetParameterByUid(PARAMETER_UID(FormProfileFamilyBuiltInParameter));
                if (param1)
                {
                    if (ut != nullptr && !ut->IsStarted())
                    {
                        ut->Start();
                    }

                    OwnerPtr<IParameterValueStorage> opParameterValueStorage = IParameterValueElementId::Create(idNewType);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterValueStorage != nullptr, L"opParameterValueStorage为空！", L"paramodel", L"2024-02-20");

                    param1->SetParameterValueStorage(TransferOwnership(opParameterValueStorage));
                    pElementParameters->SetParameter(param1.get());

                    std::vector<OwnerPtr<IParameterValueDisplayString>> opDisplayStrings;
                    gcmp::IInstanceType* pCurrentInstanceType = gcmp::quick_cast<gcmp::IInstanceType>(pCurElementType);
                    if (pCurrentInstanceType)
                    {
                        gcmp::IFamily* pCurrentFamily = pCurrentInstanceType->GetFamily();
                        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentFamily != nullptr, L"pCurrentFamily为空！", L"paramodel", L"2024-02-20");

                        const IElementBasicInformation* pFamilyBasicInformation = pCurrentFamily->GetBasicInformation();
                        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyBasicInformation != nullptr, L"pFamilyBasicInformation为空！", L"paramodel", L"2024-02-20");

                        std::vector<IInstanceType*> instanceTypes = pCurrentFamily->GetInstanceTypes();
                        FOR_EACH(instanceType, instanceTypes)
                        {
                            DBG_WARN_AND_CONTINUE_UNLESS(instanceType != nullptr, L"instanceType为空！", L"paramodel", L"2024-02-20");

                            const IElementBasicInformation* pInstanceTypeBasicInformation = instanceType->GetBasicInformation();
                            DBG_WARN_AND_CONTINUE_UNLESS(pInstanceTypeBasicInformation != nullptr, L"pInstanceTypeBasicInformation为空！", L"paramodel", L"2024-02-20");

                            OwnerPtr<IParameterValueStorage> opParamValueStorage = IParameterValueElementId::Create(pInstanceTypeBasicInformation->GetElementId());
                            DBG_WARN_AND_CONTINUE_UNLESS(opParamValueStorage != nullptr, L"opParamValueStorage为空！", L"paramodel", L"2024-02-20");
                            opDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opParamValueStorage), pFamilyBasicInformation->GetName() + L":" + pInstanceTypeBasicInformation->GetName()));
                        }

                        OwnerPtr<IParameterValueList> opValueList = IParameterValueList::CreateParameterStaticValueList(PARAMETER_UID(FormProfileFamilyBuiltInParameter), opDisplayStrings);
                        DBG_WARN_AND_RETURN_VOID_UNLESS(opValueList != nullptr, L"opValueList为空！", L"paramodel", L"2024-02-20");
                        OwnerPtr<IParameterDisplay> opParameterDisplay = IParameterDisplay::CreateParameterDisplayDropdownList(PARAMETER_UID(FormProfileFamilyBuiltInParameter), TransferOwnership(opValueList));
                        DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterDisplay != nullptr, L"opParameterDisplay为空！", L"paramodel", L"2024-02-20");
                        if (!IParameterDisplayManager::AddBuiltInParameterDisplay(TransferOwnership(opParameterDisplay)))
                        {
                            opValueList = IParameterValueList::CreateParameterStaticValueList(PARAMETER_UID(FormProfileFamilyBuiltInParameter), opDisplayStrings);
                            DBG_WARN_AND_RETURN_VOID_UNLESS(opValueList != nullptr, L"opValueList为空！", L"paramodel", L"2024-02-20");
                            opParameterDisplay = IParameterDisplay::CreateParameterDisplayDropdownList(PARAMETER_UID(FormProfileFamilyBuiltInParameter), TransferOwnership(opValueList));
                            DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterDisplay != nullptr, L"opParameterDisplay为空！", L"paramodel", L"2024-02-20");
                            IParameterDisplayManager::ReplaceBuiltInParameterDisplay(TransferOwnership(opParameterDisplay));
                        }
                    }

                    if (ut != nullptr &&ut->IsStarted())
                    {
                        ut->Commit();
                    }
                }
                OwnerPtr<IParameter> param2 = pElementParameters->GetParameterByUid(PARAMETER_UID(FormProfileFamilyBuiltInParameter1));
                if (param2)
                {
                    if (ut != nullptr && !ut->IsStarted())
                    {
                        ut->Start();
                    }

                    OwnerPtr<IParameterValueStorage> opParameterValueStorage = IParameterValueElementId::Create(idNewType);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterValueStorage != nullptr, L"opParameterValueStorage为空！", L"paramodel", L"2024-02-20");

                    param2->SetParameterValueStorage(TransferOwnership(opParameterValueStorage));
                    pElementParameters->SetParameter(param2.get());

                    std::vector<OwnerPtr<IParameterValueDisplayString>> opDisplayStrings;
                    gcmp::IInstanceType* pCurrentInstanceType = gcmp::quick_cast<gcmp::IInstanceType>(pCurElementType);
                    if (pCurrentInstanceType)
                    {
                        gcmp::IFamily* pCurrentFamily = pCurrentInstanceType->GetFamily();
                        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentFamily != nullptr, L"pCurrentFamily为空！", L"paramodel", L"2024-02-20");

                        const IElementBasicInformation* pFamilyBasicInformation = pCurrentFamily->GetBasicInformation();
                        DBG_WARN_AND_RETURN_VOID_UNLESS(pFamilyBasicInformation != nullptr, L"pFamilyBasicInformation为空！", L"paramodel", L"2024-02-20");

                        std::vector<IInstanceType*> instanceTypes = pCurrentFamily->GetInstanceTypes();
                        FOR_EACH(instanceType, instanceTypes)
                        {
                            DBG_WARN_AND_CONTINUE_UNLESS(instanceType != nullptr, L"instanceType为空！", L"paramodel", L"2024-02-20");

                            const IElementBasicInformation* pInstanceTypeBasicInformation = instanceType->GetBasicInformation();
                            DBG_WARN_AND_CONTINUE_UNLESS(pInstanceTypeBasicInformation != nullptr, L"pInstanceTypeBasicInformation为空！", L"paramodel", L"2024-02-20");

                            OwnerPtr<IParameterValueStorage> opParamValueStorage = IParameterValueElementId::Create(pInstanceTypeBasicInformation->GetElementId());
                            DBG_WARN_AND_CONTINUE_UNLESS(opParamValueStorage != nullptr, L"opParamValueStorage为空！", L"paramodel", L"2024-02-20");
                            opDisplayStrings.emplace_back(IParameterValueDisplayString::CreateParameterValueDisplayString(TransferOwnership(opParamValueStorage), pFamilyBasicInformation->GetName() + L":" + pInstanceTypeBasicInformation->GetName()));
                        }

                        OwnerPtr<IParameterValueList> opValueList = IParameterValueList::CreateParameterStaticValueList(PARAMETER_UID(FormProfileFamilyBuiltInParameter1), opDisplayStrings);
                        DBG_WARN_AND_RETURN_VOID_UNLESS(opValueList != nullptr, L"opValueList为空！", L"paramodel", L"2024-02-20");
                        OwnerPtr<IParameterDisplay> opParameterDisplay = IParameterDisplay::CreateParameterDisplayDropdownList(PARAMETER_UID(FormProfileFamilyBuiltInParameter1), TransferOwnership(opValueList));
                        DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterDisplay != nullptr, L"opParameterDisplay为空！", L"paramodel", L"2024-02-20");
                        if (!IParameterDisplayManager::AddBuiltInParameterDisplay(TransferOwnership(opParameterDisplay)))
                        {
                            opValueList = IParameterValueList::CreateParameterStaticValueList(PARAMETER_UID(FormProfileFamilyBuiltInParameter1), opDisplayStrings);
                            DBG_WARN_AND_RETURN_VOID_UNLESS(opValueList != nullptr, L"opValueList为空！", L"paramodel", L"2024-02-20");
                            opParameterDisplay = IParameterDisplay::CreateParameterDisplayDropdownList(PARAMETER_UID(FormProfileFamilyBuiltInParameter1), TransferOwnership(opValueList));
                            DBG_WARN_AND_RETURN_VOID_UNLESS(opParameterDisplay != nullptr, L"opParameterDisplay为空！", L"paramodel", L"2024-02-20");
                            IParameterDisplayManager::ReplaceBuiltInParameterDisplay(TransferOwnership(opParameterDisplay));
                        }
                    }

                    if (ut != nullptr &&ut->IsStarted())
                    {
                        ut->Commit();
                    }
                }
            }
        }

        // 3. Pop up the dialog to edit the properties of the new family type.
        if (m_familyNameValuePairsBuilder == nullptr)
        {
            m_familyNameValuePairsBuilder = NEW_AS_OWNER_PTR(FamilyNameValuePairsComponent, newFamilyName);
        }
        m_familyNameValuePairsBuilder->SetDocument(m_pDoc);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameValuePairsBuilder->GetQtEditFamilyType() != nullptr, L"m_familyNameValuePairsBuilder->GetQtEditFamilyType()为空", L"paramodel", L"2024-02-20");
        m_familyNameValuePairsBuilder->GetQtEditFamilyType()->setName(newFamilyName);
        m_familyNameValuePairsBuilder->SetElementIds({ idNewType });
        m_familyNameValuePairsBuilder->BuildNameValuePairs(true);

        DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameComponent != nullptr, L"m_familyNameComponent为空", L"paramodel", L"2024-02-20");
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_familyNameComponent->GetQtNameFamilyType() != nullptr, L"m_familyNameComponent->GetQtNameFamilyType()为空", L"paramodel", L"2024-02-20");
        gnuf::Pallet* familyTypeNamePallet = m_familyNameComponent->GetQtNameFamilyType()->pallet();
        DBG_WARN_AND_RETURN_VOID_UNLESS(familyTypeNamePallet != nullptr, L"familyTypeNamePallet为空", L"paramodel", L"2024-02-20");

        std::tuple<bool, ePreviewType> result = GnufParameterPreviewUtils::IsCanPreviewParameter(m_pDoc, typeId);
        DBG_WARN_AND_RETURN_VOID_UNLESS(familyTypeNamePallet->qtWidget() != nullptr, L"familyTypeNamePallet->qtWidget()为空", L"paramodel", L"2024-02-20");
        familyTypeNamePallet->qtWidget()->hide();
        if (1 == m_familyNameValuePairsBuilder->GetQtEditFamilyType()->popup(GBMP_TR(L"类型参数"), GnufParameterPreviewUtils::GetParentWidget(), std::get<0>(result), std::get<1>(result))) {
            return;
        }
    }
}

void gfam::FamilyTypeIntegratedComponent::refreshAppearance()
{
    if (m_familyNameValuePairsBuilder != nullptr &&
        m_familyNameValuePairsBuilder->GetQtEditFamilyType() != nullptr)
    {
        m_familyNameValuePairsBuilder->GetQtEditFamilyType()->refresh();
    }

    if (m_familyNameComponent != nullptr &&
        m_familyNameComponent->GetQtNameFamilyType() != nullptr)
    {
        m_familyNameComponent->GetQtNameFamilyType()->refresh();
    }
}

void gfam::FamilyTypeIntegratedComponent::quitTransaction()
{
    if (m_familyNameValuePairsBuilder)
    {
        m_familyNameValuePairsBuilder->quitTransaction();
    }
}

void gfam::FamilyNameValuePairsComponent::onClicked(gnuf::Item *pItem)
{
    if (pItem && pItem->type() == gnuf::EItemType::ePushButton)
    {
        OnPropertyBindButtonClicked(pItem);
    }

}

void gfam::FamilyNameValuePairsComponent::OnPropertyBindButtonClicked(gnuf::Item *pItem)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pItem, L"pItem为空", L"paramodel", L"2024-02-20");
    int uniquiID = pItem->userData().cast<ItemInfo>().ParamId;

#pragma region 以下代码属于族和构建编辑器相关功能，如需复用请酌情删除，同时删除相关头文件
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpDoc, L"m_wpDoc为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_elementIds.empty(), L"m_elementIds为空", L"paramodel", L"2024-02-20");
    IElement* pElement = m_wpDoc->GetElement(m_elementIds[0]);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement != nullptr, L"pElement为空", L"paramodel", L"2024-02-20");

    gfam::IFamilyManager *pFamManager = gfam::IFamilyManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pFamManager != nullptr, L"pFamManager为空", L"paramodel", L"2024-02-20");
    OwnerPtr<IParameter> curParam;
    int curParamDefId = -1;
    IElementParameters* pElementParameters = pElement->GetElementParameters();
    if (pElementParameters)
    {
        curParam = pElementParameters->GetParameterById(uniquiID);
        IElementParameterBindings* paramBinding = pElementParameters->GetElementParameterBindings();
        if (paramBinding)
        {
            curParamDefId = paramBinding->GetBindingSourceParameterDefinitionId(uniquiID);
        }
    }

    WorkBench* pWorkBench = WorkBench::get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pWorkBench, L"pWorkBench为空!", L"paramodel", L"2024-02-20");
    QtWorkBenchWindow* pQtWorkBenchWindow = pWorkBench->qtWorkBenchWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pQtWorkBenchWindow, L"pQtWorkBenchWindow为空!", L"paramodel", L"2024-02-20");
    GnufBindToFamilyParamDlg *pDialog = NEW_AS_QT(GnufBindToFamilyParamDlg, pQtWorkBenchWindow);
    pDialog->InitDialog(curParam.get(), curParamDefId, gfam::IFamilyManager::Get(m_wpDoc.Get()));
    if (pDialog->exec() != QDialog::Accepted)
    {
        return;
    }
    //由于GnufBindToFamilyParamDialog对话框，可能会有事务回退，会造成pFamManager 指针不稳定，所以重新获取一下
    pFamManager = gfam::IFamilyManager::Get(m_wpDoc.Get());
    Int32 newParamDefId = pDialog->GetBoundParamDefId();

    gcmp::IParameterDefinitionLibrary* paramDefinitionLibrary = gcmp::IParameterDefinitionLibrary::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(paramDefinitionLibrary, L"paramDefinitionLibrary为空", L"paramodel", L"2024-02-20");

    if (m_upUserTransaction == nullptr)
    {
        m_upUserTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改构件属性"), true);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_upUserTransaction != nullptr, L"m_upUserTransaction为空", L"paramodel", L"2024-02-20");
    }
    if (!m_upUserTransaction->IsStarted())
    {
        m_upUserTransaction->Start();
    }
    bool bRes = true;
    for (int i = 0; i < (int)m_elementIds.size(); ++i)
    {
        IElement* pSelectedElement = m_wpDoc->GetElement(m_elementIds[i]);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pSelectedElement != nullptr, L"pSelectedElement为空", L"paramodel", L"2024-02-20");

        IElementParameters* parameter = pSelectedElement->GetElementParameters();
        if (!parameter)
        {
            return;
        }
        OwnerPtr<IParameter> curParam;
        if (parameter)
        {
            curParam = parameter->GetParameterById(uniquiID);
        }
        
        if (curParam)
        {
            std::wstring errorMessage;
            int oldParamDefId = -1;
            IElementParameterBindings* paramBindings = parameter->GetElementParameterBindings();
            DBG_WARN_AND_CONTINUE_UNLESS(nullptr != paramBindings, L"paramBindings为空", L"paramodel", L"2024-02-20");

            oldParamDefId = paramBindings->GetBindingSourceParameterDefinitionId(uniquiID);

            if (newParamDefId < 0)
            {
                if (oldParamDefId > 0)
                {
                    bRes = paramBindings->DeleteParameterBinding(uniquiID);
                }
            }
            else
            {
                if (oldParamDefId > 0)
                    bRes = paramBindings->ChangeParameterBinding(uniquiID, newParamDefId, pFamManager->GetElementId());
                else
                    bRes = paramBindings->AddParameterBinding(uniquiID, newParamDefId, pFamManager->GetElementId(), false);

                if (bRes &&
                    (nullptr != FamilyElementUtils::CastElement<const IFamilyForm>(pSelectedElement)
                        || nullptr != FamilyElementUtils::CastElement<const IFamilyRapidShape>(pSelectedElement))
                    )
                {
                    std::set<const gfam::IFamilyConstraint*> failedFeatureGroup;
                    FamilySolverResult solveResult = FamilySolverUtils::SolveDocument(m_wpDoc.Get(), &failedFeatureGroup);

                    if (solveResult != FamilySolverResult::Ok)
                    {
                        errorMessage = FamilySolverUtils::GetSolverResultString(solveResult);
                        UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"参数绑定失败，") + errorMessage, (int) UiCommonDialog::ButtonType::OK);
                        m_upUserTransaction->Rollback();

                        {
                            m_upUserTransaction->Start();
                            FamilyHighlightUtils::HighlightConstraints(m_wpDoc.Get(), failedFeatureGroup, nullptr);
                            m_upUserTransaction->Commit();
                        }

                        UpdateViewVisual();
                        return;
                    }
                }
            }
            if (!bRes)
            {
                break;
            }
            const gfam::IFamilyParameterDefinition *pFamParamDef = pFamManager->GetFamilyParameterDefinition(newParamDefId);
            if (pFamParamDef != nullptr)
            {
                pFamManager->SetFamilyParameterAsDrive(pFamParamDef, curParam->IsDriveParameter());
                pFamManager->SetFamilyParameterAsGeometric(pFamParamDef, curParam->IsGeometricParameter());
            }
        }
    }
    if (bRes)
    {
        m_upUserTransaction->Commit();
        BuildNameValuePairs(false);
    }
    else
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"参数绑定失败"), (int)UiCommonDialog::ButtonType::OK);
        m_upUserTransaction->Rollback();
    }

    // 主动刷新视图
    UpdateViewVisual();
#pragma endregion
}

void gfam::FamilyNameValuePairsComponent::onCurrentIndexChanged(gnuf::List * pList, int newIndex)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pList, L"pList为空", L"paramodel", L"2024-02-20");

    //
    NameValuePair* pNameValuePair = nullptr;
    Item* pItem = pList->parent();
    while (pItem && !pNameValuePair)
    {
        pNameValuePair = pItem->cast<NameValuePair>();
        pItem = pItem->parent();
    }

    // not find , return
    if (!pNameValuePair)
        return;

    Label* pLabel = pNameValuePair->name();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pLabel, L"pLabel为空", L"paramodel", L"2024-02-20");
    std::wstring name = pLabel->text();

    auto iter = std::find_if(m_vecDisplayedParameters.begin(), m_vecDisplayedParameters.end(), [name](const gcmp::OwnerPtr<gcmp::IParameter> & parameter) {return parameter->GetName() == name; });

    if (iter == m_vecDisplayedParameters.end())
        return;

    gcmp::OwnerPtr<gcmp::IParameter> & parameter = *iter;
    DBG_WARN_AND_RETURN_VOID_UNLESS(parameter, L"parameter为空", L"paramodel", L"2024-02-20");

    const IParameterDefinition * pParameterDefinition = parameter->GetParameterDefinition();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParameterDefinition, L"pParameterDefinition为空", L"paramodel", L"2024-02-20");

    if (pParameterDefinition->GetParameterTypeId() != PARAMETER_TYPE(Material))
    {
        return;
    }

    IParameterDisplayManager* pParamDisplayManager = IParameterDisplayManager::Get(m_wpDoc.Get());
    DBG_WARN_AND_RETURN_VOID_UNLESS(pParamDisplayManager, L"pParamDisplayManager为空!", L"paramodel", L"2024-02-20");

    const IParameterDisplayDropdownList* pDisplayDropdownList = dynamic_cast<const IParameterDisplayDropdownList*>(pParamDisplayManager->GetParameterDisplay(pParameterDefinition->GetUid()));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDisplayDropdownList, L"pDisplayDropdownList为空!", L"paramodel", L"2024-02-20");


    std::wstring strCurValue = pList->Text();

    if (strCurValue.compare(L"更多材质") == 0)
    {
        ElementId materialId = ElementId::InvalidID;

        OwnerPtr<IUserTransaction> userTransaction;
        if (!IUserTransaction::IsInUserTransaction(m_wpDoc.Get(), nullptr))
        {
            userTransaction = IUserTransaction::Create(m_wpDoc.Get(), GBMP_TR(L"修改材质"), true);
            DBG_WARN_AND_RETURN_VOID_UNLESS(userTransaction, L"userTransaction为空", L"paramodel", L"2024-02-20");
        }

        UiCommonDialog::ShowMaterialSelectionDialog(m_wpDoc.Get(), materialId);

        if (!materialId.IsValid())
        {
            // 取消选择，恢复上一次选择的值
            const std::wstring displayString = pDisplayDropdownList->GetDisplayStringByValue(m_wpDoc.Get(), parameter->GetParameterValueStorage());

            int selectedIndex = FindListSelectIndex(pList->GetItemInfos(), displayString);

            if (selectedIndex >= 0)
            {
                pList->SetSelectedIndex(selectedIndex);
            }

            return;
        }

        if (userTransaction)
            userTransaction->Commit();
    }
}

void gfam::FamilyNameValuePairsComponent::UpdateViewVisual() const
{
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr != nullptr, L"pUiDocViewMgr为空", L"paramodel", L"2024-02-20");

    IUiDocument* pUIDoc = pUiDocViewMgr->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc != nullptr, L"pUIDoc为空", L"paramodel", L"2024-02-20");
    pUIDoc->UpdateViewByVisibilityConditionChanged();
    pUIDoc->UpdateView();
}

void gfam::FamilyTypeIntegratedComponent::ShowViewComponentType() const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc, L"m_pDoc为空!", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(GnufPropertyPallet::Get(), L"GnufPropertyPallet::Get()为空!", L"paramodel", L"2024-02-20");
    ElementId defaultElementId = GnufPropertyPallet::Get()->GetDefaultElementId();
    if (defaultElementId.IsValid())
    {
        IElement* pElement = m_pDoc->GetElement(defaultElementId);
        IElementBasicInformation* pElementBasicInformation = pElement->GetBasicInformation();
        std::wstring typeName;
        const IType* pType = pElementBasicInformation->GetType();
        if (pType && pType->GetBasicInformation())
        {
            typeName = pType->GetBasicInformation()->GetName();
        }
        else
        {
            typeName = pElementBasicInformation->GetName();
        }
        gnuf::Info info(GBMP_TR(L"对象类型\n") + typeName, L"", iconPath);
    }
    else
    {
        if (IUiDocumentViewManager::Get() == nullptr)
            return;

        IUiView* pUIView = IUiDocumentViewManager::Get()->GetCurrentUiView();
        if (pUIView == nullptr)
            return;

        IModelView* pModelView = pUIView->GetModelView();
        if (pModelView == nullptr)
            return;

#pragma warning(push)
#pragma warning(disable: 4996)
        std::wstring viewTypeName = gfam::GnufModelViewTypeUtil::GetModelViewTypeName(pModelView->GetUserDataId());
#pragma warning(pop)
        gnuf::Info info(GBMP_TR(L"视图名称\n") + viewTypeName, L"", L":/image/ModelView/View/3D/");
        if (m_pFamilyTypes && m_pFamilyTypes->familyTypeButton())
        {
            m_pFamilyTypes->familyTypeButton()->assignInfo(info);
        }
    }
}

void gfam::FamilyTypeIntegratedComponent::SetStatusOfAddAndModifyButton() 
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes != nullptr, L"pFamilyTypes为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDoc != nullptr, L"m_pDoc为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(!m_elementIds.empty(), L"m_elementIds为空", L"paramodel", L"2024-02-20");

    // 设置添加、编辑构件类型的两个按钮是否可用
    // 只有对实体构件才可用
    IElement* firstElement = m_pDoc->GetElement(m_elementIds[0]);
    if (!firstElement)
    {
        return;
    }

    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->addFamilyTypeButton(), L"m_pFamilyTypes->addFamilyTypeButton()为空", L"paramodel", L"2024-02-20");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->editFamilyTypeButton(), L"m_pFamilyTypes->editFamilyTypeButton()空", L"paramodel", L"2024-02-20");
    m_pFamilyTypes->addFamilyTypeButton()->setEnabled(false);
    m_pFamilyTypes->editFamilyTypeButton()->setEnabled(false);

    auto SelectedElementsAreSameCategory = [&](const std::vector<gcmp::ElementId>& selElements)->bool
    {
        if (selElements.size() > 1)
        {
            //如果选择集中多于1个，需要判断是否为同一类构件
            IElement* firstElement = m_pDoc->GetElement(selElements.at(0));
            DBG_WARN_AND_RETURN_FALSE_UNLESS(firstElement->GetBasicInformation(), L"firstElement->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
            gcmp::UniIdentity firstUid = firstElement->GetBasicInformation()->GetCategoryUid();
            gcmp::IType* firstType = firstElement->GetBasicInformation()->GetType();
            FOR_EACH(eleId, selElements)
            {
                IElement* curElement = m_pDoc->GetElement(eleId);
                DBG_WARN_AND_CONTINUE_UNLESS(curElement->GetBasicInformation(), L"curElement->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
                gcmp::IType* type = curElement->GetBasicInformation()->GetType();

                if (firstUid != curElement->GetBasicInformation()->GetCategoryUid())//类别不一样
                {
                    return false;
                }
                else if (firstType != curElement->GetBasicInformation()->GetType())//同类别，但是类型不一样
                {
                    return false;
                }
            }
        }
        return true;
    };

    DBG_WARN_AND_RETURN_VOID_UNLESS(firstElement->GetBasicInformation(), L"firstElement->GetBasicInformation()为空", L"paramodel", L"2024-02-20");
    IType* firstType = firstElement->GetBasicInformation()->GetType();
    if (firstType)
    {
        if ((IsA<IInstanceType>(firstType) || IsA<IGenericType>(firstType)) && SelectedElementsAreSameCategory(m_elementIds))
        {
            if (IsA<IInstanceType>(firstType)) 
            {
                DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->addFamilyTypeButton(), L"m_pFamilyTypes->addFamilyTypeButton()为空", L"paramodel", L"2024-02-20");
                DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->familyTypeButton(), L"m_pFamilyTypes->familyTypeButton()为空", L"paramodel", L"2024-02-20");
                m_pFamilyTypes->addFamilyTypeButton()->setEnabled(true);
                m_pFamilyTypes->familyTypeButton()->setEnabled(true);
            }
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pFamilyTypes->editFamilyTypeButton(), L"m_pFamilyTypes->editFamilyTypeButton()为空", L"paramodel", L"2024-02-20");
            m_pFamilyTypes->editFamilyTypeButton()->setEnabled(true);
        }
    }
}

gfam::FamilyTypeNameComponent::FamilyTypeNameComponent(FamilyTypeNameComponentParent * pParent, const std::wstring & name, bool wantToRename)
    : m_parent(pParent)
{
    m_qtNameFamilyType = NEW_AS_QT(QtNameFamilyType, this, name, wantToRename);
}

bool gfam::FamilyTypeNameComponent::validateFamilyTypeName(const std::wstring & name)
{
    if (name.empty())
    {
        gcmp::UiCommonDialog::ShowMessageBox(GBMP_TR(L"新建类型"), GBMP_TR(L"类型名不能为空！"), (int)gcmp::UiCommonDialog::ButtonType::OK);
        return false;
    }
    gcmp::IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc is nullptr", L"paramodel", L"2024-02-20");

    gnuf::FamilyTypes* pFamilyTypes = s_familyTypeComponentBuilder->GetFamilyTypes();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyTypes, L"pFamilyTypes is nullptr", L"paramodel", L"2024-02-20");

    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFamilyTypes->currentFamilyType(), L"pFamilyTypes->currentFamilyType() is nullptr", L"paramodel", L"2024-02-20");
    ItemInfo info = pFamilyTypes->currentFamilyType()->userData().cast<ItemInfo>();
    IType* pType = quick_cast<IType>(pDoc->GetElement(info.TypeId));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pType, L"pType is nullptr", L"paramodel", L"2024-02-20");

    if (!InputNameIsValid(pType, StringUtil::TrimSpace(name)))
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"新建类型"), GBMP_TR(L"该类型名称已使用！"), (int)UiCommonDialog::ButtonType::OK);
        return false;
    }
    return true;
}

void gfam::FamilyTypeNameComponent::onFamilyTypeNameChanged(const std::wstring & name)
{
    if (FamilyTypeIntegratedComponent* parent = dynamic_cast<FamilyTypeIntegratedComponent*>(m_parent))
    {
        if (m_parent)
        {
            m_parent->onFamilyTypeNameChanged(name);
        }
    }
}

gcmp::IDocument * gfam::FamilyTypeNameComponent::GetDocument()
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(IUiDocumentViewManager::Get(), L"IUiDocumentViewManager::Get()is nullptr", L"paramodel", L"2024-02-20");
    IUiDocument* pUiDoc = IUiDocumentViewManager::Get()->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDoc, L"pUiDoc is nullptr", L"paramodel", L"2024-02-20");

    return pUiDoc->GetDbDocument();
}
